# Secondary makefiles, conditionalized for speed
######################################################################
-# Source and binary distribution artifacts
-ifneq ($(strip $(findstring dist,$(MAKECMDGOALS)) \
- $(findstring check,$(MAKECMDGOALS)) \
- $(findstring test,$(MAKECMDGOALS)) \
- $(findstring tidy,$(MAKECMDGOALS)) \
- $(findstring clean,$(MAKECMDGOALS))),)
- CFG_INFO := $(info cfg: including dist rules)
- include $(CFG_SRC_DIR)mk/dist.mk
-endif
-
# Binary snapshots
ifneq ($(strip $(findstring snap,$(MAKECMDGOALS)) \
$(findstring clean,$(MAKECMDGOALS))),)
include $(CFG_SRC_DIR)mk/perf.mk
endif
-# Cleaning
-ifneq ($(findstring clean,$(MAKECMDGOALS)),)
- CFG_INFO := $(info cfg: including clean rules)
- include $(CFG_SRC_DIR)mk/clean.mk
+# Copy all the distributables to another directory for binary install
+ifneq ($(strip $(findstring prepare,$(MAKECMDGOALS)) \
+ $(findstring dist,$(MAKECMDGOALS)) \
+ $(findstring install,$(MAKECMDGOALS))),)
+ CFG_INFO := $(info cfg: including prepare rules)
+ include $(CFG_SRC_DIR)mk/prepare.mk
endif
-# Installation from the build directory
+# (Unix) Installation from the build directory
ifneq ($(findstring install,$(MAKECMDGOALS)),)
CFG_INFO := $(info cfg: including install rules)
include $(CFG_SRC_DIR)mk/install.mk
endif
+# Source and binary distribution artifacts
+ifneq ($(strip $(findstring dist,$(MAKECMDGOALS)) \
+ $(findstring clean,$(MAKECMDGOALS))),)
+ CFG_INFO := $(info cfg: including dist rules)
+ include $(CFG_SRC_DIR)mk/dist.mk
+endif
+
+# Cleaning
+ifneq ($(findstring clean,$(MAKECMDGOALS)),)
+ CFG_INFO := $(info cfg: including clean rules)
+ include $(CFG_SRC_DIR)mk/clean.mk
+endif
+
# CTAGS building
ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \
$(findstring TAGS.vi,$(MAKECMDGOALS))),)
$(S)RELEASES.txt \
$(S)configure $(S)Makefile.in \
$(S)man \
- $(S)doc \
$(addprefix $(S)src/, \
README.md \
compiletest \
+ doc \
driver \
etc \
$(foreach crate,$(CRATES),lib$(crate)) \
cp $< $@
$(PKG_EXE): rust.iss modpath.iss LICENSE.txt rust-logo.ico \
- $(PKG_FILES) $(CSREQ3_T_$(CFG_BUILD)_H_$(CFG_BUILD))
- $(CFG_PYTHON) $(S)src/etc/copy-runtime-deps.py i686-pc-mingw32/stage3/bin
+ $(PKG_FILES) $(CSREQ3_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
+ dist-prepare-win
+ $(CFG_PYTHON) $(S)src/etc/copy-runtime-deps.py tmp/dist/win/bin
@$(call E, ISCC: $@)
$(Q)"$(CFG_ISCC)" $<
-endif
+dist-prepare-win: PREPARE_HOST=$(CFG_BUILD)
+dist-prepare-win: PREPARE_TARGETS=$(CFG_BUILD)
+dist-prepare-win: PREPARE_DEST_DIR=tmp/dist/win
+# On windows we're using stage3, unlike Unix...
+dist-prepare-win: PREPARE_STAGE=3
+dist-prepare-win: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
+dist-prepare-win: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
+dist-prepare-win: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
+dist-prepare-win: PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
+dist-prepare-win: prepare-base
+
+endif
$(PKG_TAR): $(PKG_FILES)
@$(call E, making dist dir)
# For consistency it might be desirable for stageN to be an exact
# mirror of the installation directory structure.
-# Installation macros.
-# For INSTALL,
-# $(1) is the source dirctory
-# $(2) is the destination directory
-# $(3) is the filename/libname-glob
-ifdef VERBOSE
- INSTALL = install -m755 $(1)/$(3) $(DESTDIR)$(2)/$(3)
-else
- INSTALL = $(Q)$(call E, install: $(DESTDIR)$(2)/$(3)) && install -m755 $(1)/$(3) $(DESTDIR)$(2)/$(3)
-endif
-
-# For MK_INSTALL_DIR
-# $(1) is the directory to create
-MK_INSTALL_DIR = (umask 022 && mkdir -p $(DESTDIR)$(1))
-
-# For INSTALL_LIB,
-# Target-specific $(LIB_SOURCE_DIR) is the source directory
-# Target-specific $(LIB_DESTIN_DIR) is the destination directory
-# $(1) is the filename/libname-glob
-ifdef VERBOSE
- DO_INSTALL_LIB = install -m644 `ls -drt1 $(LIB_SOURCE_DIR)/$(1) | tail -1` $(DESTDIR)$(LIB_DESTIN_DIR)/
-else
- DO_INSTALL_LIB = $(Q)$(call E, install_lib: $(DESTDIR)$(LIB_DESTIN_DIR)/$(1)) && \
- install -m644 `ls -drt1 $(LIB_SOURCE_DIR)/$(1) | tail -1` $(DESTDIR)$(LIB_DESTIN_DIR)/
-endif
-
-# Target-specific $(LIB_SOURCE_DIR) is the source directory
-# Target-specific $(LIB_DESTIN_DIR) is the destination directory
-# $(1) is the filename/libname-glob
-define INSTALL_LIB
- $(if $(filter-out 1,$(words $(wildcard $(LIB_SOURCE_DIR)/$(1)))), \
- $(error Aborting install because more than one library matching \
- $(1) is present in build tree $(LIB_SOURCE_DIR): \
- $(wildcard $(LIB_SOURCE_DIR)/$(1))))
- $(Q)LIB_NAME="$(notdir $(lastword $(wildcard $(LIB_SOURCE_DIR)/$(1))))"; \
- MATCHES="$(filter-out %$(notdir $(lastword $(wildcard $(LIB_SOURCE_DIR)/$(1)))),\
- $(wildcard $(LIB_DESTIN_DIR)/$(1)))"; \
- if [ -n "$$MATCHES" ]; then \
- echo "warning: one or libraries matching Rust library '$(1)'" && \
- echo " (other than '$$LIB_NAME' itself) already present" && \
- echo " at destination $(LIB_DESTIN_DIR):" && \
- echo $$MATCHES ; \
- fi
- $(call DO_INSTALL_LIB,$(1))
-endef
-
# The stage we install from
ISTAGE = 2
+install: PREPARE_HOST=$(CFG_BUILD)
+install: PREPARE_TARGETS=$(CFG_TARGET)
+install: PREPARE_STAGE=$(ISTAGE)
+install: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
+install: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
+install: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
+install: PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
+install: PREPARE_SOURCE_DIR=$(PREPARE_HOST)/stage$(PREPARE_STAGE)
+install: PREPARE_SOURCE_BIN_DIR=$(PREPARE_SOURCE_DIR)/bin
+install: PREPARE_SOURCE_LIB_DIR=$(PREPARE_SOURCE_DIR)/$(CFG_LIBDIR_RELATIVE)
+install: PREPARE_SOURCE_MAN_DIR=$(S)/man
+install: PREPARE_DEST_BIN_DIR=$(DESTDIR)$(CFG_PREFIX)/bin
+install: PREPARE_DEST_LIB_DIR=$(DESTDIR)$(CFG_LIBDIR)
+install: PREPARE_DEST_MAN_DIR=$(DESTDIR)$(CFG_MANDIR)/man1
+install: prepare-everything
+
+
+# Uninstall code
+
PREFIX_ROOT = $(CFG_PREFIX)
PREFIX_BIN = $(PREFIX_ROOT)/bin
PREFIX_LIB = $(CFG_LIBDIR)
-INSTALL_TOOLS := $(filter-out compiletest, $(TOOLS))
-
-define INSTALL_PREPARE_N
- # $(1) is the target triple
- # $(2) is the host triple
-
-# T{B,L} == Target {Bin, Lib} for stage ${ISTAGE}
-TB$(1)$(2) = $$(TBIN$$(ISTAGE)_T_$(1)_H_$(2))
-TL$(1)$(2) = $$(TLIB$$(ISTAGE)_T_$(1)_H_$(2))
-
-# PT{R,B,L} == Prefix Target {Root, Bin, Lib}
-PTR$(1)$(2) = $$(PREFIX_LIB)/$(CFG_RUSTLIBDIR)/$(1)
-PTB$(1)$(2) = $$(PTR$(1)$(2))/bin
-PTL$(1)$(2) = $$(PTR$(1)$(2))/lib
-
-endef
-
-$(foreach target,$(CFG_TARGET), \
- $(eval $(call INSTALL_PREPARE_N,$(target),$(CFG_BUILD))))
-
-define INSTALL_TARGET_N
-install-target-$(1)-host-$(2): LIB_SOURCE_DIR=$$(TL$(1)$(2))
-install-target-$(1)-host-$(2): LIB_DESTIN_DIR=$$(PTL$(1)$(2))
-install-target-$(1)-host-$(2): \
- $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2)) \
- $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2))
- $$(Q)$$(call MK_INSTALL_DIR,$$(PTL$(1)$(2)))
- $$(Q)$$(foreach crate,$$(TARGET_CRATES),\
- $$(call INSTALL_LIB,$$(call CFG_LIB_GLOB_$(1),$$(crate)));\
- $$(call INSTALL_LIB,$$(call CFG_RLIB_GLOB,$$(crate)));)
- $$(Q)$$(call INSTALL_LIB,libmorestack.a)
- $$(Q)$$(call INSTALL_LIB,libcompiler-rt.a)
-
-endef
-
-define INSTALL_HOST_N
-
-install-target-$(1)-host-$(2): LIB_SOURCE_DIR=$$(TL$(1)$(2))
-install-target-$(1)-host-$(2): LIB_DESTIN_DIR=$$(PTL$(1)$(2))
-install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2))
- $$(Q)$$(call MK_INSTALL_DIR,$$(PTL$(1)$(2)))
- $$(Q)$$(foreach crate,$$(CRATES),\
- $$(call INSTALL_LIB,$$(call CFG_LIB_GLOB_$(1),$$(crate)));)
- $$(Q)$$(foreach crate,$$(TARGET_CRATES),\
- $$(call INSTALL_LIB,$$(call CFG_RLIB_GLOB,$$(crate)));)
- $$(Q)$$(call INSTALL_LIB,libmorestack.a)
- $$(Q)$$(call INSTALL_LIB,libcompiler-rt.a)
-endef
-
-$(foreach target,$(CFG_TARGET), \
- $(if $(findstring $(target), $(CFG_BUILD)), \
- $(eval $(call INSTALL_HOST_N,$(target),$(CFG_BUILD))), \
- $(eval $(call INSTALL_TARGET_N,$(target),$(CFG_BUILD)))))
-
-INSTALL_TARGET_RULES = $(foreach target,$(CFG_TARGET), \
- install-target-$(target)-host-$(CFG_BUILD))
-
-install: all install-host install-targets
+INSTALL_TOOLS := $(PREPARE_TOOLS)
# Shorthand for build/stageN/bin
HB = $(HBIN$(ISTAGE)_H_$(CFG_BUILD))
# Shorthand for the prefix bin directory
PHL = $(PREFIX_LIB)
-install-host%: LIB_SOURCE_DIR=$(HL)
-install-host%: LIB_DESTIN_DIR=$(PHL)
-install-host: \
- install-host-prep \
- $(foreach tool,$(INSTALL_TOOLS),install-host-tool-$(tool))
-
-install-host-prep: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD)_H_$(CFG_BUILD))
- $(Q)$(call MK_INSTALL_DIR,$(PREFIX_BIN))
- $(Q)$(call MK_INSTALL_DIR,$(PREFIX_LIB))
- $(Q)$(call MK_INSTALL_DIR,$(CFG_MANDIR)/man1)
-
-define INSTALL_HOST_TOOL
-install-host-tool-$(1): \
- $$(foreach dep,$$(TOOL_DEPS_$(1)),install-host-lib-$$(dep)) \
- $$(CSREQ$$(ISTAGE)_T_$$(CFG_BUILD)_H_$$(CFG_BUILD))
- $$(Q)$$(call INSTALL,$$(HB2),$$(PHB),$(1)$$(X_$$(CFG_BUILD)))
- $$(Q)$$(call INSTALL,$$(S)/man,$$(CFG_MANDIR)/man1,$(1).1)
-endef
-
-$(foreach tool,$(INSTALL_TOOLS),$(eval $(call INSTALL_HOST_TOOL,$(tool))))
-
-define INSTALL_HOST_LIB
-install-host-lib-$(1): \
- $$(foreach dep,$$(RUST_DEPS_$(1)),install-host-lib-$$(dep)) \
- $$(CSREQ$$(ISTAGE)_T_$$(CFG_BUILD)_H_$$(CFG_BUILD))
- $$(Q)$$(call INSTALL_LIB,$$(call CFG_LIB_GLOB_$$(CFG_BUILD),$(1)))
-endef
-
-$(foreach lib,$(CRATES),$(eval $(call INSTALL_HOST_LIB,$(lib))))
-
-install-targets: $(INSTALL_TARGET_RULES)
-
-
HOST_LIB_FROM_HL_GLOB = \
$(patsubst $(HL)/%,$(PHL)/%,$(wildcard $(HL)/$(1)))
$(foreach lib,$(CRATES),$(eval $(call UNINSTALL_LIB,$(lib))))
+
+# Android runtime setup
+# FIXME: This probably belongs somewhere else
+
# target platform specific variables
# for arm-linux-androidabi
define DEF_ADB_DEVICE_STATUS
--- /dev/null
+# Copyright 2014 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.
+
+# Basic support for producing installation images.
+#
+# The 'prepare' build target copies all release artifacts from the build
+# directory to some other location, placing all binaries, libraries, and
+# docs in their final locations relative to each other.
+#
+# It requires the following variables to be set:
+#
+# PREPARE_HOST - the host triple
+# PREPARE_TARGETS - the target triples, space separated
+# PREPARE_DEST_DIR - the directory to put the image
+
+prepare: PREPARE_STAGE=2
+prepare: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
+prepare: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
+prepare: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
+prepare: PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
+prepare: prepare-base
+
+prepare-base: PREPARE_SOURCE_DIR=$(PREPARE_HOST)/stage$(PREPARE_STAGE)
+prepare-base: PREPARE_SOURCE_BIN_DIR=$(PREPARE_SOURCE_DIR)/bin
+prepare-base: PREPARE_SOURCE_LIB_DIR=$(PREPARE_SOURCE_DIR)/$(CFG_LIBDIR_RELATIVE)
+prepare-base: PREPARE_SOURCE_MAN_DIR=$(S)/man
+prepare-base: PREPARE_DEST_BIN_DIR=$(PREPARE_DEST_DIR)/bin
+prepare-base: PREPARE_DEST_LIB_DIR=$(PREPARE_DEST_DIR)/$(CFG_LIBDIR_RELATIVE)
+prepare-base: PREPARE_DEST_MAN_DIR=$(PREPARE_DEST_DIR)/man1
+prepare-base: prepare-host prepare-targets
+
+prepare-everything: prepare-host prepare-targets
+
+DEFAULT_PREPARE_DIR_CMD = umask 022 && mkdir -p
+DEFAULT_PREPARE_BIN_CMD = install -m755
+DEFAULT_PREPARE_LIB_CMD = install -m644
+DEFAULT_PREPARE_MAN_CMD = install -m755
+
+# On windows we install from stage3, but on unix only stage2
+# Because of the way these rules are organized, preparing from any
+# stage requires all these stages to be built
+ifdef CFG_WINDOWSY_$(CFG_BUILD)
+PREPARE_STAGES=3
+else
+PREPARE_STAGES=2
+endif
+
+# Create a directory
+# $(1) is the directory
+define PREPARE_DIR
+ @$(Q)$(call E, install: $(1))
+ $(Q)$(PREPARE_DIR_CMD) $(1)
+endef
+
+# Copy an executable
+# $(1) is the filename/libname-glob
+define PREPARE_BIN
+ @$(call E, install: $(PREPARE_DEST_BIN_DIR)/$(1))
+ $(Q)$(PREPARE_BIN_CMD) $(PREPARE_SOURCE_BIN_DIR)/$(1) $(PREPARE_DEST_BIN_DIR)/$(1)
+endef
+
+# Copy a dylib or rlib
+# $(1) is the filename/libname-glob
+#
+# XXX: Don't remove the $(nop) command below!
+# Yeah, that's right, it's voodoo. Something in the way this macro is being expanded
+# causes it to parse incorrectly. Throwing in that empty command seems to fix the
+# problem. I'm sorry, just don't remove the $(nop), alright?
+define PREPARE_LIB
+ $(nop)
+ @$(call E, install: $(PREPARE_WORKING_DEST_LIB_DIR)/$(1))
+ $(Q)LIB_NAME="$(notdir $(lastword $(wildcard $(PREPARE_WORKING_SOURCE_LIB_DIR)/$(1))))"; \
+ MATCHES="$(filter-out %$(notdir $(lastword $(wildcard $(PREPARE_WORKING_SOURCE_LIB_DIR)/$(1)))),\
+ $(wildcard $(PREPARE_WORKING_DEST_LIB_DIR)/$(1)))"; \
+ if [ -n "$$MATCHES" ]; then \
+ echo "warning: one or libraries matching Rust library '$(1)'" && \
+ echo " (other than '$$LIB_NAME' itself) already present" && \
+ echo " at destination $(PREPARE_WORKING_DEST_LIB_DIR):" && \
+ echo $$MATCHES ; \
+ fi
+ $(Q)$(PREPARE_LIB_CMD) `ls -drt1 $(PREPARE_WORKING_SOURCE_LIB_DIR)/$(1) | tail -1` $(PREPARE_WORKING_DEST_LIB_DIR)/
+endef
+
+# Copy a man page
+# $(1) - source dir
+define PREPARE_MAN
+ @$(call E, install: $(PREPARE_DEST_MAN_DIR)/$(1))
+ $(Q)$(PREPARE_MAN_CMD) $(PREPARE_SOURCE_MAN_DIR)/$(1) $(PREPARE_DEST_MAN_DIR)/$(1)
+endef
+
+
+PREPARE_TOOLS = $(filter-out compiletest, $(TOOLS))
+
+prepare-host: prepare-host-tools
+
+prepare-host-tools: \
+ $(foreach tool, $(PREPARE_TOOLS),\
+ $(foreach stage,$(PREPARE_STAGES),\
+ $(foreach host,$(CFG_HOST),\
+ prepare-host-tool-$(tool)-$(stage)-$(host))))
+
+prepare-host-dirs:
+ $(call PREPARE_DIR,$(PREPARE_DEST_BIN_DIR))
+ $(call PREPARE_DIR,$(PREPARE_DEST_LIB_DIR))
+ $(call PREPARE_DIR,$(PREPARE_DEST_MAN_DIR))
+
+# $(1) is tool
+# $(2) is stage
+# $(3) is host
+define DEF_PREPARE_HOST_TOOL
+prepare-host-tool-$(1)-$(2)-$(3): $$(foreach dep,$$(TOOL_DEPS_$(1)),prepare-host-lib-$$(dep)-$(2)-$(3)) \
+ $$(HBIN$(2)_H_$(3))/$(1)$$(X_$(3)) \
+ prepare-host-dirs
+ $$(if $$(findstring $(2), $$(PREPARE_STAGE)),\
+ $$(if $$(findstring $(3), $$(PREPARE_HOST)),\
+ $$(call PREPARE_BIN,$(1)$$(X_$$(PREPARE_HOST))),),)
+ $$(if $$(findstring $(2), $$(PREPARE_STAGE)),\
+ $$(if $$(findstring $(3), $$(PREPARE_HOST)),\
+ $$(call PREPARE_MAN,$(1).1),),)
+endef
+
+$(foreach tool,$(PREPARE_TOOLS),\
+ $(foreach stage,$(PREPARE_STAGES),\
+ $(foreach host,$(CFG_HOST),\
+ $(eval $(call DEF_PREPARE_HOST_TOOL,$(tool),$(stage),$(host))))))
+
+# For host libraries only install dylibs, not rlibs since the host libs are only
+# used to support rustc and rustc uses dynamic linking
+#
+# $(1) is tool
+# $(2) is stage
+# $(3) is host
+define DEF_PREPARE_HOST_LIB
+prepare-host-lib-$(1)-$(2)-$(3): PREPARE_WORKING_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_LIB_DIR)
+prepare-host-lib-$(1)-$(2)-$(3): PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_LIB_DIR)
+prepare-host-lib-$(1)-$(2)-$(3): $$(foreach dep,$$(RUST_DEPS_$(1)),prepare-host-lib-$$(dep)-$(2)-$(3))\
+ $$(HLIB$(2)_H_$(3))/stamp.$(1) \
+ prepare-host-dirs
+ $$(if $$(findstring $(2), $$(PREPARE_STAGE)),\
+ $$(if $$(findstring $(3), $$(PREPARE_HOST)),\
+ $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$$(PREPARE_HOST),$(1))),),)
+endef
+
+$(foreach lib,$(CRATES),\
+ $(foreach stage,$(PREPARE_STAGES),\
+ $(foreach host,$(CFG_HOST),\
+ $(eval $(call DEF_PREPARE_HOST_LIB,$(lib),$(stage),$(host))))))
+
+prepare-targets:\
+ $(foreach host,$(CFG_HOST),\
+ $(foreach target,$(CFG_TARGET),\
+ $(foreach stage,$(PREPARE_STAGES),\
+ prepare-target-$(target)-host-$(host)-$(stage))))
+
+# $(1) is stage
+# $(2) is target
+# $(3) is host
+define DEF_PREPARE_TARGET_N
+# Rebind PREPARE_*_LIB_DIR to point to rustlib, then install the libs for the targets
+prepare-target-$(2)-host-$(3)-$(1): PREPARE_WORKING_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_LIB_DIR)/$$(CFG_RUSTLIBDIR)/$(2)/lib
+prepare-target-$(2)-host-$(3)-$(1): PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_LIB_DIR)/$$(CFG_RUSTLIBDIR)/$(2)/lib
+prepare-target-$(2)-host-$(3)-$(1): \
+ $$(foreach crate,$$(TARGET_CRATES), \
+ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) \
+ $$(if $$(findstring $(2),$$(CFG_HOST)), \
+ $$(foreach crate,$$(HOST_CRATES), \
+ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)),)
+# Only install if this host and target combo is being prepared
+ $$(if $$(findstring $(1), $$(PREPARE_STAGE)),\
+ $$(if $$(findstring $(2), $$(PREPARE_TARGETS)),\
+ $$(if $$(findstring $(3), $$(PREPARE_HOST)),\
+ $$(call PREPARE_DIR,$$(PREPARE_WORKING_DEST_LIB_DIR))\
+ $$(foreach crate,$$(TARGET_CRATES),\
+ $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))\
+ $$(call PREPARE_LIB,$$(call CFG_RLIB_GLOB,$$(crate))))\
+ $$(if $$(findstring $(2),$$(CFG_HOST)),\
+ $$(foreach crate,$$(HOST_CRATES),\
+ $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))\
+ $$(call PREPARE_LIB,$$(call CFG_RLIB_GLOB,$$(crate)))),)\
+ $$(call PREPARE_LIB,libmorestack.a) \
+ $$(call PREPARE_LIB,libcompiler-rt.a),),),)
+endef
+
+$(foreach host,$(CFG_HOST),\
+ $(foreach target,$(CFG_TARGET), \
+ $(foreach stage,$(PREPARE_STAGES),\
+ $(eval $(call DEF_PREPARE_TARGET_N,$(stage),$(target),$(host))))))
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/etc -name '*.py' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
+ $(Q)find $(S)src/doc -name '*.js' \
+ | xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
+ $(Q)find $(S)src/etc -name '*.sh' \
+ | xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
+ $(Q)find $(S)src/etc -name '*.pl' \
+ | xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
+ $(Q)find $(S)src/etc -name '*.c' \
+ | xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
+ $(Q)find $(S)src/etc -name '*.h' \
+ | xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)echo $(ALL_CS) \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)echo $(ALL_HS) \
+// Copyright (C) 2013 by Marijn Haverbeke <marijnh@gmail.com> and others
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
exports.htmlEscape = function(text) {
var replacements = {"<": "<", ">": ">",
"&": "&", "\"": """};
if (string == "\n")
accum.push("<br>");
else if (style)
- accum.push("<span class=\"cm-" + exports.htmlEscape(style) + "\">" + exports.htmlEscape(string) + "</span>");
+ accum.push("<span class=\"cm-" + exports.htmlEscape(style) + "\">" +
+ exports.htmlEscape(string) + "</span>");
else
accum.push(exports.htmlEscape(string));
}
+// Copyright (C) 2013 by Marijn Haverbeke <marijnh@gmail.com> and others
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
CodeMirror.defineMode("rust", function() {
var indentUnit = 4, altIndentUnit = 2;
var valKeywords = {
type = lexical.type, closing = firstChar == type;
if (type == "stat") return lexical.indented + indentUnit;
if (lexical.align) return lexical.column + (closing ? 0 : 1);
- return lexical.indented + (closing ? 0 : (lexical.info == "match" ? altIndentUnit : indentUnit));
+ return lexical.indented +
+ (closing ? 0 : (lexical.info == "match" ? altIndentUnit : indentUnit));
},
electricChars: "{}"
#!/usr/local/bin/node
+// Copyright 2014 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.
+
/***
* Pandoc-style markdown preprocessor that drops extra directives
* included for running doc code, and that optionally, when
+# Copyright 2014 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.
+#
+# ignore-tidy-linelength
#
# usage : adb_run_wrapper [test dir - where test executables exist] [test executable]
#
#!/usr/bin/perl -w
+# Copyright 2014 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.
my $file = $ARGV[0];
+// Copyright 2014 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 a helper C program for generating required math constants
//
// Should only be required when porting to a different target architecture
+# Copyright 2014 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 runs the test for emacs rust-mode.
# It must be possible to find emacs via PATH.
emacs -batch -l rust-mode.el -l rust-mode-tests.el -f ert-run-tests-batch-and-exit
+// Copyright 2014 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 calculates the platform-variable portion of the libc module.
* Move code in here only as you discover it is platform-variable.
"""
exceptions = [
+ "doc/lib/codemirror-node.js", # MIT
+ "doc/lib/codemirror-rust.js", # MIT
"rt/rust_android_dummy.cpp", # BSD, chromium
"rt/rust_android_dummy.h", # BSD, chromium
"rt/isaac/randport.cpp", # public domain
#!/bin/sh
+# Copyright 2014 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.
TARG_DIR=$1
PREFIX=$2
OS=`uname -s`
case $OS in
("Linux"|"FreeBSD")
- BIN_SUF=
- LIB_SUF=.so
- break
- ;;
+ BIN_SUF=
+ LIB_SUF=.so
+ break
+ ;;
("Darwin")
- BIN_SUF=
- LIB_SUF=.dylib
- break
- ;;
+ BIN_SUF=
+ LIB_SUF=.dylib
+ break
+ ;;
(*)
- BIN_SUF=.exe
- LIB_SUF=.dll
- LIB_DIR=bin
- LIB_PREFIX=
- break
- ;;
+ BIN_SUF=.exe
+ LIB_SUF=.dll
+ LIB_DIR=bin
+ LIB_PREFIX=
+ break
+ ;;
esac
if [ -z $PREFIX ]; then
+// Copyright 2014 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.
+
#ifndef _FIX_CXXCONFIG_H
#define _FIX_CXXCONFIG_H 1
+// Copyright 2014 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.
+
#ifndef _FIX_WINBASE_H
#define _FIX_WINBASE_H 1
+// Copyright 2014 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.
+
#ifndef _FIX_WINSOCK2_H
#define _FIX_WINSOCK2_H 1
Name: modifypath; Description: &Add {app}\bin to your PATH (recommended)
[Files]
-Source: "i686-pc-mingw32/stage3/*.*" ; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
+Source: "tmp/dist/win/*.*" ; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
[Code]
const
}
fn size_hint(&self) -> (uint, Option<uint>) {
- let exact = self.bits.population_count();
+ let exact = self.bits.count_ones();
(exact, Some(exact))
}
}
monitor_ch: Chan<MonitorMsg>,
testfn: proc()) {
spawn(proc() {
- let mut task = task::task();
let (p, c) = Chan::new();
let mut reader = PortReader::new(p);
let stdout = ChanWriter::new(c.clone());
let stderr = ChanWriter::new(c);
- match desc.name {
- DynTestName(ref name) => task.name(name.clone()),
- StaticTestName(name) => task.name(name),
- }
+ let mut task = task::task().named(match desc.name {
+ DynTestName(ref name) => name.clone().into_maybe_owned(),
+ StaticTestName(name) => name.into_maybe_owned(),
+ });
task.opts.stdout = Some(~stdout as ~Writer);
task.opts.stderr = Some(~stderr as ~Writer);
let result_future = task.future_result();
opts: TaskOpts,
f: proc()) -> ~GreenTask {
let TaskOpts {
- watched: _watched,
notify_chan, name, stack_size,
stderr, stdout, logger,
} = opts;
/// inside the task.
pub fn spawn_opts(opts: TaskOpts, f: proc()) {
let TaskOpts {
- watched: _watched,
notify_chan, name, stack_size,
logger, stderr, stdout,
} = opts;
#[cfg(not(rtopt))]
static STACK_SIZE: uint = 20000000; // 20MB
- let mut task_builder = task::task();
- task_builder.name("rustc");
+ let mut task_builder = task::task().named("rustc");
// FIXME: Hacks on hacks. If the env is trying to override the stack size
// then *don't* set it explicitly.
use syntax::abi;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
-use syntax::codemap::{Span, DUMMY_SP};
+use syntax::codemap::{Span};
use syntax::diagnostic::SpanHandler;
use syntax::ext::base::{CrateLoader, MacroCrate};
use syntax::parse::token::{IdentInterner, InternedString};
match extract_crate_info(i) {
Some(info) => {
let cnum = resolve_crate(e,
+ None,
info.ident.clone(),
info.name.clone(),
info.version.clone(),
}
fn resolve_crate(e: &mut Env,
+ root_ident: Option<~str>,
ident: ~str,
name: ~str,
version: ~str,
};
let loader::Library {
dylib, rlib, metadata
- } = load_ctxt.load_library_crate();
+ } = load_ctxt.load_library_crate(root_ident.clone());
let attrs = decoder::get_crate_attributes(metadata.as_slice());
let crateid = attr::find_crateid(attrs).unwrap();
}
e.next_crate_num += 1;
+ // Maintain a reference to the top most crate.
+ let root_crate = match root_ident {
+ Some(c) => c,
+ None => load_ctxt.ident.clone()
+ };
+
// Now resolve the crates referenced by this crate
- let cnum_map = resolve_crate_deps(e, metadata.as_slice());
+ let cnum_map = resolve_crate_deps(e,
+ Some(root_crate),
+ metadata.as_slice(),
+ span);
let cmeta = @cstore::crate_metadata {
name: load_ctxt.name,
}
// Go through the crate metadata and load any crates that it references
-fn resolve_crate_deps(e: &mut Env, cdata: &[u8]) -> cstore::cnum_map {
+fn resolve_crate_deps(e: &mut Env,
+ root_ident: Option<~str>,
+ cdata: &[u8], span : Span)
+ -> cstore::cnum_map {
debug!("resolving deps of external crate");
// The map from crate numbers in the crate we're resolving to local crate
// numbers
None => {
debug!("need to load it");
// This is a new one so we've got to load it
- // FIXME (#2404): Need better error reporting than just a bogus
- // span.
- let fake_span = DUMMY_SP;
let local_cnum = resolve_crate(e,
+ root_ident.clone(),
cname_str.get().to_str(),
cname_str.get().to_str(),
dep.vers.clone(),
dep.hash.clone(),
- fake_span);
+ span);
cnum_map.insert(extrn_cnum, local_cnum);
}
}
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
let info = extract_crate_info(krate).unwrap();
let cnum = resolve_crate(&mut self.env,
+ None,
info.ident.clone(),
info.name.clone(),
info.version.clone(),
}
impl Context {
- pub fn load_library_crate(&self) -> Library {
+ pub fn load_library_crate(&self, root_ident: Option<~str>) -> Library {
match self.find_library_crate() {
Some(t) => t,
None => {
- self.sess.span_fatal(self.span,
- format!("can't find crate for `{}`",
- self.ident));
+ let message = match root_ident {
+ None => format!("can't find crate for `{}`", self.ident),
+ Some(c) => format!("can't find crate for `{}` which `{}` depends on",
+ self.ident,
+ c)
+ };
+ self.sess.span_fatal(self.span, message);
}
}
}
4 => Type::array(&Type::i32(), align_units),
8 if machine::llalign_of_min(cx, Type::i64()) == 8 =>
Type::array(&Type::i64(), align_units),
- a if a.population_count() == 1 => Type::array(&Type::vector(&Type::i32(), a / 4),
+ a if a.count_ones() == 1 => Type::array(&Type::vector(&Type::i32(), a / 4),
align_units),
_ => fail!("unsupported enum alignment: {:?}", align)
};
}
}
+fn ensure_generics_abi(ccx: &CrateCtxt,
+ span: Span,
+ abis: AbiSet,
+ generics: &ast::Generics) {
+ if generics.ty_params.len() > 0 &&
+ !(abis.is_rust() || abis.is_intrinsic()) {
+ ccx.tcx.sess.span_err(span,
+ "foreign functions may not use type parameters");
+ }
+}
+
pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
let tcx = ccx.tcx;
debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
match it.node {
- // These don't define types.
- ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
- ast::ItemEnum(ref enum_definition, ref generics) => {
- ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
- let tpt = ty_of_item(ccx, it);
- write_ty_to_tcx(tcx, it.id, tpt.ty);
- get_enum_variant_types(ccx,
- tpt.ty,
- enum_definition.variants,
- generics);
- }
- ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
- let i_ty_generics = ty_generics(ccx, generics, 0);
- let selfty = ccx.to_ty(&ExplicitRscope, selfty);
- write_ty_to_tcx(tcx, it.id, selfty);
+ // These don't define types.
+ ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
+ ast::ItemEnum(ref enum_definition, ref generics) => {
+ ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
+ let tpt = ty_of_item(ccx, it);
+ write_ty_to_tcx(tcx, it.id, tpt.ty);
+ get_enum_variant_types(ccx,
+ tpt.ty,
+ enum_definition.variants,
+ generics);
+ },
+ ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
+ let i_ty_generics = ty_generics(ccx, generics, 0);
+ let selfty = ccx.to_ty(&ExplicitRscope, selfty);
+ write_ty_to_tcx(tcx, it.id, selfty);
- {
- let mut tcache = tcx.tcache.borrow_mut();
- tcache.get().insert(local_def(it.id),
- ty_param_bounds_and_ty {
- generics: i_ty_generics.clone(),
- ty: selfty});
- }
+ {
+ let mut tcache = tcx.tcache.borrow_mut();
+ tcache.get().insert(local_def(it.id),
+ ty_param_bounds_and_ty {
+ generics: i_ty_generics.clone(),
+ ty: selfty});
+ }
- // If there is a trait reference, treat the methods as always public.
- // This is to work around some incorrect behavior in privacy checking:
- // when the method belongs to a trait, it should acquire the privacy
- // from the trait, not the impl. Forcing the visibility to be public
- // makes things sorta work.
- let parent_visibility = if opt_trait_ref.is_some() {
- ast::Public
- } else {
- it.vis
- };
+ // If there is a trait reference, treat the methods as always public.
+ // This is to work around some incorrect behavior in privacy checking:
+ // when the method belongs to a trait, it should acquire the privacy
+ // from the trait, not the impl. Forcing the visibility to be public
+ // makes things sorta work.
+ let parent_visibility = if opt_trait_ref.is_some() {
+ ast::Public
+ } else {
+ it.vis
+ };
- convert_methods(ccx,
- ImplContainer(local_def(it.id)),
- *ms,
- selfty,
- &i_ty_generics,
- generics,
- parent_visibility);
-
- for trait_ref in opt_trait_ref.iter() {
- let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
-
- // Prevent the builtin kind traits from being manually implemented.
- if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
- tcx.sess.span_err(it.span,
- "cannot provide an explicit implementation \
- for a builtin kind");
+ convert_methods(ccx,
+ ImplContainer(local_def(it.id)),
+ *ms,
+ selfty,
+ &i_ty_generics,
+ generics,
+ parent_visibility);
+
+ for trait_ref in opt_trait_ref.iter() {
+ let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
+
+ // Prevent the builtin kind traits from being manually implemented.
+ if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
+ tcx.sess.span_err(it.span,
+ "cannot provide an explicit implementation \
+ for a builtin kind");
+ }
}
- }
- }
- ast::ItemTrait(ref generics, _, ref trait_methods) => {
- let trait_def = trait_def_of_item(ccx, it);
-
- // Run convert_methods on the provided methods.
- let (_, provided_methods) =
- split_trait_methods(*trait_methods);
- let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
- convert_methods(ccx,
- TraitContainer(local_def(it.id)),
- provided_methods,
- untransformed_rcvr_ty,
- &trait_def.generics,
- generics,
- it.vis);
-
- // We need to do this *after* converting methods, since
- // convert_methods produces a tcache entry that is wrong for
- // static trait methods. This is somewhat unfortunate.
- ensure_trait_methods(ccx, it.id);
- }
- ast::ItemStruct(struct_def, ref generics) => {
- ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
-
- // Write the class type
- let tpt = ty_of_item(ccx, it);
- write_ty_to_tcx(tcx, it.id, tpt.ty);
+ },
+ ast::ItemTrait(ref generics, _, ref trait_methods) => {
+ let trait_def = trait_def_of_item(ccx, it);
+
+ // Run convert_methods on the provided methods.
+ let (_, provided_methods) =
+ split_trait_methods(*trait_methods);
+ let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
+ convert_methods(ccx,
+ TraitContainer(local_def(it.id)),
+ provided_methods,
+ untransformed_rcvr_ty,
+ &trait_def.generics,
+ generics,
+ it.vis);
+
+ // We need to do this *after* converting methods, since
+ // convert_methods produces a tcache entry that is wrong for
+ // static trait methods. This is somewhat unfortunate.
+ ensure_trait_methods(ccx, it.id);
+ },
+ ast::ItemStruct(struct_def, ref generics) => {
+ ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
+
+ // Write the class type
+ let tpt = ty_of_item(ccx, it);
+ write_ty_to_tcx(tcx, it.id, tpt.ty);
- {
- let mut tcache = tcx.tcache.borrow_mut();
- tcache.get().insert(local_def(it.id), tpt.clone());
- }
+ {
+ let mut tcache = tcx.tcache.borrow_mut();
+ tcache.get().insert(local_def(it.id), tpt.clone());
+ }
- convert_struct(ccx, struct_def, tpt, it.id);
- }
- ast::ItemTy(_, ref generics) => {
- ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
- let tpt = ty_of_item(ccx, it);
- write_ty_to_tcx(tcx, it.id, tpt.ty);
- }
- _ => {
- // This call populates the type cache with the converted type
- // of the item in passing. All we have to do here is to write
- // it into the node type table.
- let tpt = ty_of_item(ccx, it);
- write_ty_to_tcx(tcx, it.id, tpt.ty);
- }
+ convert_struct(ccx, struct_def, tpt, it.id);
+ },
+ ast::ItemTy(_, ref generics) => {
+ ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
+ let tpt = ty_of_item(ccx, it);
+ write_ty_to_tcx(tcx, it.id, tpt.ty);
+ },
+ ast::ItemFn(_, _, abi, ref generics, _) => {
+ ensure_generics_abi(ccx, it.span, abi, generics);
+ let tpt = ty_of_item(ccx, it);
+ write_ty_to_tcx(tcx, it.id, tpt.ty);
+ },
+ _ => {
+ // This call populates the type cache with the converted type
+ // of the item in passing. All we have to do here is to write
+ // it into the node type table.
+ let tpt = ty_of_item(ccx, it);
+ write_ty_to_tcx(tcx, it.id, tpt.ty);
+ },
}
}
#[desc = "rustdoc, the Rust documentation extractor"];
#[license = "MIT/ASL2"];
#[crate_type = "dylib"];
+#[crate_type = "rlib"];
#[feature(globs, struct_variant, managed_boxes)];
// See the discussion in the stream implementation for why we we
// might decrement steals.
Some(data) => {
- self.steals += 1;
if self.steals > MAX_STEALS {
match self.cnt.swap(0, atomics::SeqCst) {
DISCONNECTED => {
n => {
let m = cmp::min(n, self.steals);
self.steals -= m;
- self.cnt.fetch_add(n - m, atomics::SeqCst);
+ self.bump(n - m);
}
}
assert!(self.steals >= 0);
}
+ self.steals += 1;
Ok(data)
}
// down as much as possible (without going negative), and then
// adding back in whatever we couldn't factor into steals.
Some(data) => {
- self.steals += 1;
if self.steals > MAX_STEALS {
match self.cnt.swap(0, atomics::SeqCst) {
DISCONNECTED => {
n => {
let m = cmp::min(n, self.steals);
self.steals -= m;
- self.cnt.fetch_add(n - m, atomics::SeqCst);
+ self.bump(n - m);
}
}
assert!(self.steals >= 0);
}
+ self.steals += 1;
match data {
Data(t) => Ok(t),
GoUp(up) => Err(Upgraded(up)),
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
format trait used is the `Show` trait. This is one of the more commonly
implemented traits when formatting a custom type.
-When implementing a format trait for your own time, you will have to implement a
+When implementing a format trait for your own type, you will have to implement a
method of the signature:
```rust
impl fmt::Show for Vector2D {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- // The `f.buf` value is of the type `&mut io::Writer`, which is what th
+ // The `f.buf` value is of the type `&mut io::Writer`, which is what the
// write! macro is expecting. Note that this formatting ignores the
// various flags provided to format strings.
write!(f.buf, "({}, {})", self.x, self.y)
int_module!(i16, 16)
impl Bitwise for i16 {
- /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ /// Returns the number of ones in the binary representation of the number.
#[inline]
- fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
+ fn count_ones(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
- /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
#[inline]
fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } }
- /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ /// Returns the number of trailing zeros in the in the binary representation
+ /// of the number.
#[inline]
fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } }
}
int_module!(i32, 32)
impl Bitwise for i32 {
- /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ /// Returns the number of ones in the binary representation of the number.
#[inline]
- fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
+ fn count_ones(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
- /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
#[inline]
fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } }
- /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ /// Returns the number of trailing zeros in the in the binary representation
+ /// of the number.
#[inline]
fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } }
}
int_module!(i64, 64)
impl Bitwise for i64 {
- /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ /// Returns the number of ones in the binary representation of the number.
#[inline]
- fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
+ fn count_ones(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
- /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
#[inline]
fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } }
- /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ /// Counts the number of trailing zeros.
#[inline]
fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } }
}
int_module!(i8, 8)
impl Bitwise for i8 {
- /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ /// Returns the number of ones in the binary representation of the number.
#[inline]
- fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
+ fn count_ones(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
- /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
#[inline]
fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } }
- /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ /// Returns the number of trailing zeros in the in the binary representation
+ /// of the number.
#[inline]
fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } }
}
#[cfg(target_word_size = "32")]
impl Bitwise for int {
- /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ /// Returns the number of ones in the binary representation of the number.
#[inline]
- fn population_count(&self) -> int { (*self as i32).population_count() as int }
+ fn count_ones(&self) -> int { (*self as i32).count_ones() as int }
- /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
#[inline]
fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int }
- /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ /// Returns the number of trailing zeros in the in the binary representation
+ /// of the number.
#[inline]
fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int }
}
#[cfg(target_word_size = "64")]
impl Bitwise for int {
- /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ /// Returns the number of ones in the binary representation of the number.
#[inline]
- fn population_count(&self) -> int { (*self as i64).population_count() as int }
+ fn count_ones(&self) -> int { (*self as i64).count_ones() as int }
- /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
#[inline]
fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int }
- /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ /// Returns the number of trailing zeros in the in the binary representation
+ /// of the number.
#[inline]
fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int }
}
}
#[test]
- fn test_bitcount() {
- assert_eq!((0b010101 as $T).population_count(), 3);
+ fn test_count_ones() {
+ assert_eq!((0b0101100 as $T).count_ones(), 3);
+ assert_eq!((0b0100001 as $T).count_ones(), 2);
+ assert_eq!((0b1111001 as $T).count_ones(), 5);
+ }
+
+ #[test]
+ fn test_count_zeros() {
+ assert_eq!((0b0101100 as $T).count_zeros(), BITS as $T - 3);
+ assert_eq!((0b0100001 as $T).count_zeros(), BITS as $T - 2);
+ assert_eq!((0b1111001 as $T).count_zeros(), BITS as $T - 5);
}
#[test]
+ BitXor<Self,Self>
+ Shl<Self,Self>
+ Shr<Self,Self> {
- /// Returns the number of bits set in the number.
+ /// Returns the number of ones in the binary representation of the number.
///
/// # Example
///
/// ```rust
/// use std::num::Bitwise;
///
- /// let n = 0b0101000u16;
- /// assert_eq!(n.population_count(), 2);
+ /// let n = 0b01001100u8;
+ /// assert_eq!(n.count_ones(), 3);
/// ```
- fn population_count(&self) -> Self;
- /// Returns the number of leading zeros in the number.
+ fn count_ones(&self) -> Self;
+
+ /// Returns the number of zeros in the binary representation of the number.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use std::num::Bitwise;
+ ///
+ /// let n = 0b01001100u8;
+ /// assert_eq!(n.count_zeros(), 5);
+ /// ```
+ #[inline]
+ fn count_zeros(&self) -> Self {
+ (!*self).count_ones()
+ }
+
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
///
/// # Example
///
/// assert_eq!(n.leading_zeros(), 10);
/// ```
fn leading_zeros(&self) -> Self;
- /// Returns the number of trailing zeros in the number.
+
+ /// Returns the number of trailing zeros in the in the binary representation
+ /// of the number.
///
/// # Example
///
impl Primitive for $T {}
impl Bitwise for $T {
- /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ /// Returns the number of ones in the binary representation of the number.
#[inline]
- fn population_count(&self) -> $T {
- (*self as $T_SIGNED).population_count() as $T
+ fn count_ones(&self) -> $T {
+ (*self as $T_SIGNED).count_ones() as $T
}
- /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ /// Returns the number of leading zeros in the in the binary representation
+ /// of the number.
#[inline]
fn leading_zeros(&self) -> $T {
(*self as $T_SIGNED).leading_zeros() as $T
}
- /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ /// Returns the number of trailing zeros in the in the binary representation
+ /// of the number.
#[inline]
fn trailing_zeros(&self) -> $T {
(*self as $T_SIGNED).trailing_zeros() as $T
}
#[test]
- fn test_bitcount() {
- assert_eq!((0b010101 as $T).population_count(), 3);
+ fn test_count_ones() {
+ assert_eq!((0b0101100 as $T).count_ones(), 3);
+ assert_eq!((0b0100001 as $T).count_ones(), 2);
+ assert_eq!((0b1111001 as $T).count_ones(), 5);
+ }
+
+ #[test]
+ fn test_count_zeros() {
+ assert_eq!((0b0101100 as $T).count_zeros(), BITS as $T - 3);
+ assert_eq!((0b0100001 as $T).count_zeros(), BITS as $T - 2);
+ assert_eq!((0b1111001 as $T).count_zeros(), BITS as $T - 5);
}
#[test]
*
* An executing Rust program consists of a tree of tasks, each with their own
* stack, and sole ownership of their allocated heap data. Tasks communicate
- * with each other using ports and channels (see std::rt::comm for more info
+ * with each other using ports and channels (see std::comm for more info
* about how communication works).
*
- * Tasks can be spawned in 3 different modes.
- *
- * * Bidirectionally linked: This is the default mode and it's what ```spawn``` does.
- * Failures will be propagated from parent to child and vice versa.
- *
- * * Unidirectionally linked (parent->child): This type of task can be created with
- * ```spawn_supervised```. In this case, failures are propagated from parent to child
- * but not the other way around.
- *
- * * Unlinked: Tasks can be completely unlinked. These tasks can be created by using
- * ```spawn_unlinked```. In this case failures are not propagated at all.
- *
- * Tasks' failure modes can be further configured. For instance, parent tasks can (un)watch
- * children failures. Please, refer to TaskBuilder's documentation bellow for more information.
- *
- * When a (bi|uni)directionally linked task fails, its failure will be propagated to all tasks
- * linked to it, this will cause such tasks to fail by a `linked failure`.
+ * Failure in one task does not propagate to any others (not to parent, not to child).
+ * Failure propagation is instead handled by using Chan.send() and Port.recv(), which
+ * will fail if the other end has hung up already.
*
* Task Scheduling:
*
* ```
*/
-#[allow(missing_doc)];
-
use any::Any;
use comm::{Chan, Port};
use io::Writer;
/// Indicates the manner in which a task exited.
///
/// A task that completes without failing is considered to exit successfully.
-/// Supervised ancestors and linked siblings may yet fail after this task
-/// succeeds. Also note that in such a case, it may be nondeterministic whether
-/// linked failure or successful exit happen first.
///
-/// If you wish for this result's delivery to block until all linked and/or
+/// If you wish for this result's delivery to block until all
/// children tasks complete, recommend using a result future.
pub type TaskResult = Result<(), ~Any>;
-/**
- * Task configuration options
- *
- * # Fields
- *
- * * watched - Make parent task collect exit status notifications from child
- * before reporting its own exit status. (This delays the parent
- * task's death and cleanup until after all transitively watched
- * children also exit.) True by default.
- *
- * * notify_chan - Enable lifecycle notifications on the given channel
- *
- * * name - A name for the task-to-be, for identification in failure messages.
- *
- * * sched - Specify the configuration of a new scheduler to create the task
- * in. This is of particular importance for libraries which want to call
- * into foreign code that blocks. Without doing so in a different
- * scheduler other tasks will be impeded or even blocked indefinitely.
- */
+/// Task configuration options
pub struct TaskOpts {
- watched: bool,
+ /// Enable lifecycle notifications on the given channel
notify_chan: Option<Chan<TaskResult>>,
+ /// A name for the task-to-be, for identification in failure messages
name: Option<SendStr>,
+ /// The size of the stack for the spawned task
stack_size: Option<uint>,
+ /// Task-local logger (see std::logging)
logger: Option<~Logger>,
+ /// Task-local stdout
stdout: Option<~Writer>,
+ /// Task-local stderr
stderr: Option<~Writer>,
}
// sidestep that whole issue by making builders uncopyable and making
// the run function move them in.
pub struct TaskBuilder {
+ /// Options to spawn the new task with
opts: TaskOpts,
priv gen_body: Option<proc(v: proc()) -> proc()>,
priv nopod: Option<marker::NoPod>,
/**
* Generate the base configuration for spawning a task, off of which more
* configuration methods can be chained.
- * For example, task().unlinked().spawn is equivalent to spawn_unlinked.
*/
pub fn task() -> TaskBuilder {
TaskBuilder {
}
impl TaskBuilder {
- /// Cause the parent task to collect the child's exit status (and that of
- /// all transitively-watched grandchildren) before reporting its own.
- pub fn watched(&mut self) {
- self.opts.watched = true;
- }
-
- /// Allow the child task to outlive the parent task, at the possible cost
- /// of the parent reporting success even if the child task fails later.
- pub fn unwatched(&mut self) {
- self.opts.watched = false;
- }
-
/// Get a future representing the exit status of the task.
///
/// Taking the value of the future will block until the child task
/// spawned; as such, do not invoke .get() on it directly;
/// rather, store it in an outer variable/list for later use.
///
- /// Note that the future returned by this function is only useful for
- /// obtaining the value of the next task to be spawning with the
- /// builder. If additional tasks are spawned with the same builder
- /// then a new result future must be obtained prior to spawning each
- /// task.
- ///
/// # Failure
/// Fails if a future_result was already set for this task.
pub fn future_result(&mut self) -> Port<TaskResult> {
/// Name the task-to-be. Currently the name is used for identification
/// only in failure messages.
- pub fn name<S: IntoMaybeOwned<'static>>(&mut self, name: S) {
+ pub fn named<S: IntoMaybeOwned<'static>>(mut self, name: S) -> TaskBuilder {
self.opts.name = Some(name.into_maybe_owned());
+ self
}
/**
* generator by applying the task body which results from the
* existing body generator to the new body generator.
*/
- pub fn add_wrapper(&mut self, wrapper: proc(v: proc()) -> proc()) {
+ pub fn with_wrapper(mut self, wrapper: proc(v: proc()) -> proc()) -> TaskBuilder {
let prev_gen_body = self.gen_body.take();
let prev_gen_body = match prev_gen_body {
Some(gen) => gen,
f
};
self.gen_body = Some(next_gen_body);
+ self
}
/**
* Sets up a new task with its own call stack and schedules it to run
* the provided unique closure. The task has the properties and behavior
* specified by the task_builder.
- *
- * # Failure
- *
- * When spawning into a new scheduler, the number of threads requested
- * must be greater than zero.
*/
pub fn spawn(mut self, f: proc()) {
let gen_body = self.gen_body.take();
pub fn new() -> TaskOpts {
/*!
* The default task options
- *
- * By default all tasks are supervised by their parent, are spawned
- * into the same scheduler, and do not post lifecycle notifications.
*/
TaskOpts {
- watched: true,
notify_chan: None,
name: None,
stack_size: None,
* Execute a function in another task and return either the return value
* of the function or result::err.
*
- * This is equivalent to task().supervised().try.
+ * This is equivalent to task().try.
*/
let task = task();
#[test]
fn test_owned_named_task() {
- let mut t = task();
- t.name(~"ada lovelace");
- t.spawn(proc() {
+ task().named(~"ada lovelace").spawn(proc() {
with_task_name(|name| {
assert!(name.unwrap() == "ada lovelace");
})
#[test]
fn test_static_named_task() {
- let mut t = task();
- t.name("ada lovelace");
- t.spawn(proc() {
+ task().named("ada lovelace").spawn(proc() {
with_task_name(|name| {
assert!(name.unwrap() == "ada lovelace");
})
#[test]
fn test_send_named_task() {
- let mut t = task();
- t.name("ada lovelace".into_maybe_owned());
- t.spawn(proc() {
+ task().named("ada lovelace".into_maybe_owned()).spawn(proc() {
with_task_name(|name| {
assert!(name.unwrap() == "ada lovelace");
})
}
#[test]
-fn test_add_wrapper() {
+fn test_with_wrapper() {
let (po, ch) = Chan::new();
- let mut b0 = task();
- b0.add_wrapper(proc(body) {
+ task().with_wrapper(proc(body) {
let ch = ch;
let result: proc() = proc() {
body();
ch.send(());
};
result
- });
- b0.spawn(proc() { });
+ }).spawn(proc() { });
po.recv();
}
fn child_no(x: uint) -> proc() {
return proc() {
if x < generations {
- let mut t = task();
- t.unwatched();
- t.spawn(child_no(x+1));
+ task().spawn(child_no(x+1));
}
}
}
- let mut t = task();
- t.unwatched();
- t.spawn(child_no(0));
+ task().spawn(child_no(0));
}
#[test]
--- /dev/null
+// Copyright 2014 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.
+
+extern "C" fn foo<T>() {} //~ERROR foreign functions may not use type parameters
+
+fn main() {
+ let _ = foo::<int>;
+}
use std::task;
fn main() {
- let mut t = task::task();
- t.name(~"owned name");
- t.try(proc() {
+ task::task().named(~"owned name").try(proc() {
fail!("test");
1
}).unwrap()
// error-pattern:task 'send name' failed at 'test'
fn main() {
- let mut t = ::std::task::task();
- t.name("send name".into_maybe_owned());
- t.try(proc() {
+ ::std::task::task().named("send name".into_maybe_owned()).try(proc() {
fail!("test");
3
}).unwrap()
// error-pattern:task 'static name' failed at 'test'
fn main() {
- let mut t = ::std::task::task();
- t.name("static name");
- t.try(proc() {
+ ::std::task::task().named("static name").try(proc() {
fail!("test");
}).unwrap()
}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) --crate-type=rlib crateA.rs
+ $(RUSTC) --crate-type=rlib crateB.rs
+ rm $(TMPDIR)/$(call RLIB_GLOB,crateA)
+ # Ensure crateC fails to compile since dependency crateA is missing
+ $(RUSTC) crateC.rs 2>&1 | \
+ grep "error: can't find crate for \`crateA\` which \`crateB\` depends on"
--- /dev/null
+// Copyright 2014 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.
+
+// Base crate
+pub fn func() {}
--- /dev/null
+// Copyright 2014 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.
+
+extern crate crateA;
--- /dev/null
+// Copyright 2014 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.
+
+extern crate crateB;
+
+fn main() {}