Merge "Windows: Update build-mingw64-toolchain.sh for modern versions."
diff --git a/build/core/build-binary.mk b/build/core/build-binary.mk
index 379c323..1fa3021 100644
--- a/build/core/build-binary.mk
+++ b/build/core/build-binary.mk
@@ -239,9 +239,9 @@
 #
 LOCAL_OBJECTS := $(LOCAL_SRC_FILES)
 $(foreach _ext,$(all_source_extensions),\
-    $(eval LOCAL_OBJECTS := $$(LOCAL_OBJECTS:%$(_ext)=%.o))\
+    $(eval LOCAL_OBJECTS := $$(LOCAL_OBJECTS:%$(_ext)=%$$(TARGET_OBJ_EXTENSION)))\
 )
-LOCAL_OBJECTS := $(filter %.o,$(LOCAL_OBJECTS))
+LOCAL_OBJECTS := $(filter %$(TARGET_OBJ_EXTENSION),$(LOCAL_OBJECTS))
 LOCAL_OBJECTS := $(subst ../,__/,$(LOCAL_OBJECTS))
 LOCAL_OBJECTS := $(foreach _obj,$(LOCAL_OBJECTS),$(LOCAL_OBJS_DIR)/$(_obj))
 
@@ -259,7 +259,7 @@
 #
 ifneq (,$(call module-has-c++-features,$(LOCAL_MODULE),rtti exceptions))
     ifeq (system,$(NDK_APP_STL))
-      LOCAL_LDLIBS := $(LOCAL_LDLIBS) $(call host-path,$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/libsupc++.a)
+      LOCAL_LDLIBS := $(LOCAL_LDLIBS) $(call host-path,$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/libsupc++$(TARGET_LIB_EXTENSION))
     endif
 endif
 
@@ -282,21 +282,6 @@
 #
 # Handle the static and shared libraries this module depends on
 #
-LOCAL_STATIC_LIBRARIES       := $(call strip-lib-prefix,$(LOCAL_STATIC_LIBRARIES))
-LOCAL_WHOLE_STATIC_LIBRARIES := $(call strip-lib-prefix,$(LOCAL_WHOLE_STATIC_LIBRARIES))
-LOCAL_SHARED_LIBRARIES       := $(call strip-lib-prefix,$(LOCAL_SHARED_LIBRARIES))
-
-# Transitive closure of static libraries
-LOCAL_STATIC_LIBRARIES       := $(call module-get-depends,$(LOCAL_STATIC_LIBRARIES),STATIC_LIBRARIES)
-LOCAL_WHOLE_STATIC_LIBRARIES := $(call module-get-depends,$(LOCAL_WHOLE_STATIC_LIBRARIES),WHOLE_STATIC_LIBRARIES)
-
-static_libraries       := $(call map,module-get-built,$(LOCAL_STATIC_LIBRARIES))
-whole_static_libraries := $(call map,module-get-built,$(LOCAL_WHOLE_STATIC_LIBRARIES))
-
-shared_libraries := $(call map,module-get-built,$(LOCAL_SHARED_LIBRARIES))\
-                    $(TARGET_PREBUILT_SHARED_LIBRARIES)
-
-$(LOCAL_BUILT_MODULE): $(static_libraries) $(whole_static_libraries) $(shared_libraries)
 
 # If LOCAL_LDLIBS contains anything like -l<library> then
 # prepend a -L$(SYSROOT)/usr/lib to it to ensure that the linker
@@ -306,20 +291,6 @@
     LOCAL_LDLIBS := -L$(call host-path,$(SYSROOT)/usr/lib) $(LOCAL_LDLIBS)
 endif
 
-# The list of object/static/shared libraries passed to the linker when
-# building shared libraries and executables. order is important.
-#
-# Cannot use immediate evaluation because PRIVATE_LIBGCC may not be defined at this point.
-linker_objects_and_libraries = $(strip $(call TARGET-get-linker-objects-and-libraries,\
-    $(LOCAL_OBJECTS), \
-    $(static_libraries), \
-    $(whole_static_libraries), \
-    $(shared_libraries)))
-
-# The list of object files sent to 'ar' when building static libraries
-#
-ar_objects := $(call host-path,$(LOCAL_OBJECTS))
-
 # When LOCAL_SHORT_COMMANDS is defined to 'true' we are going to write the
 # list of all object files and/or static/shared libraries that appear on the
 # command line to a file, then use the @<listfile> syntax to invoke it.
@@ -331,39 +302,10 @@
 ifndef LOCAL_SHORT_COMMANDS
     LOCAL_SHORT_COMMANDS := $(strip $(NDK_APP_SHORT_COMMANDS))
 endif
-ifeq ($(LOCAL_SHORT_COMMANDS),true)
-    # For static and whole static libraries
-    ifneq (,$(filter STATIC_LIBRARY WHOLE_STATIC_LIBRARY,$(call module-get-class,$(LOCAL_MODULE))))
-        $(call ndk_log,Building static library module '$(LOCAL_MODULE)' with linker list file)
-        ar_options   := $(ar_objects)
-        ar_list_file := $(LOCAL_OBJS_DIR)/archiver.list
-        ar_objects   := @$(call host-path,$(ar_list_file))
-        $(call generate-list-file,$(ar_options),$(ar_list_file))
-
-        $(LOCAL_BUILT_MODULE): $(ar_list_file)
-    endif
-
-    # For shared libraries and executables
-    ifneq (,$(filter SHARED_LIBRARY EXECUTABLE,$(call module-get-class,$(LOCAL_MODULE))))
-        $(call ndk_log,Building ELF binary module '$(LOCAL_MODULE)' with linker list file)
-        linker_options   := $(linker_objects_and_libraries)
-        linker_list_file := $(LOCAL_OBJS_DIR)/linker.list
-        linker_objects_and_libraries := @$(call host-path,$(linker_list_file))
-
-        $(call generate-list-file,$(linker_options),$(linker_list_file))
-
-        $(LOCAL_BUILT_MODULE): $(linker_list_file)
-    endif
-
-endif
 
 $(call generate-file-dir,$(LOCAL_BUILT_MODULE))
 
-$(LOCAL_BUILT_MODULE): PRIVATE_STATIC_LIBRARIES := $(static_libraries)
-$(LOCAL_BUILT_MODULE): PRIVATE_WHOLE_STATIC_LIBRARIES := $(whole_static_libraries)
-$(LOCAL_BUILT_MODULE): PRIVATE_SHARED_LIBRARIES := $(shared_libraries)
-$(LOCAL_BUILT_MODULE): PRIVATE_OBJECTS          := $(LOCAL_OBJECTS)
-$(LOCAL_BUILT_MODULE): PRIVATE_LINKER_OBJECTS_AND_LIBRARIES := $(linker_objects_and_libraries)
+$(LOCAL_BUILT_MODULE): PRIVATE_OBJECTS := $(LOCAL_OBJECTS)
 $(LOCAL_BUILT_MODULE): PRIVATE_LIBGCC := $(TARGET_LIBGCC)
 
 $(LOCAL_BUILT_MODULE): PRIVATE_LD := $(TARGET_LD)
@@ -373,29 +315,137 @@
 $(LOCAL_BUILT_MODULE): PRIVATE_NAME := $(notdir $(LOCAL_BUILT_MODULE))
 $(LOCAL_BUILT_MODULE): PRIVATE_CXX := $(TARGET_CXX)
 $(LOCAL_BUILT_MODULE): PRIVATE_CC := $(TARGET_CC)
-$(LOCAL_BUILT_MODULE): PRIVATE_AR := $(TARGET_AR) $(TARGET_ARFLAGS)
-$(LOCAL_BUILT_MODULE): PRIVATE_AR_OBJECTS := $(ar_objects)
 $(LOCAL_BUILT_MODULE): PRIVATE_SYSROOT := $(SYSROOT)
-$(LOCAL_BUILT_MODULE): PRIVATE_BUILD_SHARED_LIB := $(cmd-build-shared-library)
-$(LOCAL_BUILT_MODULE): PRIVATE_BUILD_STATIC_LIB := $(cmd-build-static-library)
-$(LOCAL_BUILT_MODULE): PRIVATE_BUILD_EXECUTABLE := $(cmd-build-executable)
+
+ifeq ($(call module-get-class,$(LOCAL_MODULE)),STATIC_LIBRARY)
 
 #
-# If this is a static library module
+# This is a static library module, things are very easy. We only need
+# to build the object files and archive them with 'ar'. Note that module
+# dependencies can be ignored here, i.e. if the module depends on other
+# static or shared libraries, there is no need to actually build them
+# before, so don't add Make dependencies to them.
 #
-ifeq ($(call module-get-class,$(LOCAL_MODULE)),STATIC_LIBRARY)
+# In other words, consider the following graph:
+#
+#     libfoo.so -> libA.a ->libB.a
+#
+# then libA.a and libB.a can be built in parallel, only linking libfoo.so
+# depends on their completion.
+#
+
+ar_objects := $(call host-path,$(LOCAL_OBJECTS))
+
+ifeq ($(LOCAL_SHORT_COMMANDS),true)
+    $(call ndk_log,Building static library module '$(LOCAL_MODULE)' with linker list file)
+    ar_list_file := $(LOCAL_OBJS_DIR)/archiver.list
+    $(call generate-list-file,$(ar_objects),$(ar_list_file))
+    ar_objects   := @$(call host-path,$(ar_list_file))
+    $(LOCAL_BUILT_MODULE): $(ar_list_file)
+endif
+
+$(LOCAL_BUILT_MODULE): PRIVATE_AR := $(TARGET_AR) $(TARGET_ARFLAGS)
+$(LOCAL_BUILT_MODULE): PRIVATE_AR_OBJECTS := $(ar_objects)
+$(LOCAL_BUILT_MODULE): PRIVATE_BUILD_STATIC_LIB := $(cmd-build-static-library)
+
 $(LOCAL_BUILT_MODULE): $(LOCAL_OBJECTS)
 	@ $(HOST_ECHO) "StaticLibrary  : $(PRIVATE_NAME)"
 	$(hide) $(call host-rm,$@)
 	$(hide) $(PRIVATE_BUILD_STATIC_LIB)
 
 ALL_STATIC_LIBRARIES += $(LOCAL_BUILT_MODULE)
+
+endif
+
+ifneq (,$(filter SHARED_LIBRARY EXECUTABLE,$(call module-get-class,$(LOCAL_MODULE))))
+
+#
+# This is a shared library or an executable, so computing dependencies properly is
+# crucial. The general rule to apply is the following:
+#
+#   - collect the list of all static libraries that need to be part
+#     of the link, and in the right order. To do so, get the transitive
+#     closure of LOCAL_STATIC_LIBRARIES and LOCAL_WHOLE_STATIC_LIBRARIES
+#     and ensure they are ordered topologically.
+#
+#  - collect the list of all shared libraries that need to be part of
+#    the link. This is the transitive closure of the list of
+#    LOCAL_SHARED_LIBRARIES for the module and all its dependent static
+#    libraries identified in the step above. Of course, need to be
+#    ordered topologically too.
+#
+#  - add Make dependencies to ensure that all these libs are built
+#    before the module itself too.
+#
+# A few quick examples:
+#
+#    main.exe -> libA.a -> libB.a -> libfoo.so -> libC.a
+#
+#      static_libs(main.exe) = libA.a libB.a  (i.e. no libC.a)
+#      shared_libs(main.exe) = libfoo.so
+#      static_libs(libfoo.so) = libC.a
+#
+#    main.exe -> libA.a ---> libB.a
+#                  |           ^
+#                  v           |
+#                libC.a  ------
+#
+#      static_libs(main.exe) = libA.a libC.a libB.a
+#             (i.e. libB.a must appear after all libraries that depend on it).
+#
+all_libs := $(call module-get-link-libs,$(LOCAL_MODULE))
+shared_libs := $(call module-filter-shared-libraries,$(all_libs))
+static_libs := $(call module-filter-static-libraries,$(all_libs))
+whole_static_libs := $(call module-extract-whole-static-libs,$(LOCAL_MODULE),$(static_libs))
+static_libs := $(filter-out $(whole_static_libs),$(static_libs))
+
+$(call -ndk-mod-debug,module $(LOCAL_MODULE) [$(LOCAL_BUILT_MODULE)])
+$(call -ndk-mod-debug,.  all_libs='$(all_libs)')
+$(call -ndk-mod-debug,.  shared_libs='$(shared_libs)')
+$(call -ndk-mod-debug,.  static_libs='$(static_libs)')
+$(call -ndk-mod-debug,.  whole_static_libs='$(whole_static_libs)')
+
+shared_libs       := $(call map,module-get-built,$(shared_libs))\
+                     $(TARGET_PREBUILT_SHARED_LIBRARIES)
+static_libs       := $(call map,module-get-built,$(static_libs))
+whole_static_libs := $(call map,module-get-built,$(whole_static_libs))
+
+$(call -ndk-mod-debug,.  built_shared_libs='$(shared_libs)')
+$(call -ndk-mod-debug,.  built_static_libs='$(static_libs)')
+$(call -ndk-mod-debug,.  built_whole_static_libs='$(whole_static_libs)')
+
+ifeq ($(LOCAL_SHORT_COMMANDS),true)
+    $(call ndk_log,Building ELF binary module '$(LOCAL_MODULE)' with linker list file)
+    linker_options   := $(linker_objects_and_libraries)
+    linker_list_file := $(LOCAL_OBJS_DIR)/linker.list
+    linker_objects_and_libraries := @$(call host-path,$(linker_list_file))
+    $(call generate-list-file,$(linker_options),$(linker_list_file))
+    $(LOCAL_BUILT_MODULE): $(linker_list_file)
+endif
+
+# The list of object/static/shared libraries passed to the linker when
+# building shared libraries and executables. order is important.
+#
+# Cannot use immediate evaluation because PRIVATE_LIBGCC may not be defined at this point.
+linker_objects_and_libraries = $(strip $(call TARGET-get-linker-objects-and-libraries,\
+    $(LOCAL_OBJECTS), \
+    $(static_libs), \
+    $(whole_static_libs), \
+    $(shared_libs)))
+
+$(LOCAL_BUILT_MODULE): $(shared_libs) $(static_libs) $(whole_static_libs)
+$(LOCAL_BUILT_MODULE): PRIVATE_LINKER_OBJECTS_AND_LIBRARIES := $(linker_objects_and_libraries)
+$(LOCAL_BUILT_MODULE): PRIVATE_STATIC_LIBRARIES := $(static_libs)
+$(LOCAL_BUILT_MODULE): PRIVATE_WHOLE_STATIC_LIBRARIES := $(whole_static_libs))
+$(LOCAL_BUILT_MODULE): PRIVATE_SHARED_LIBRARIES := $(shared_libs))
+
 endif
 
 #
 # If this is a shared library module
 #
 ifeq ($(call module-get-class,$(LOCAL_MODULE)),SHARED_LIBRARY)
+$(LOCAL_BUILT_MODULE): PRIVATE_BUILD_SHARED_LIB := $(cmd-build-shared-library)
 $(LOCAL_BUILT_MODULE): $(LOCAL_OBJECTS)
 	@ $(HOST_ECHO) "SharedLibrary  : $(PRIVATE_NAME)"
 	$(hide) $(PRIVATE_BUILD_SHARED_LIB)
@@ -407,6 +457,7 @@
 # If this is an executable module
 #
 ifeq ($(call module-get-class,$(LOCAL_MODULE)),EXECUTABLE)
+$(LOCAL_BUILT_MODULE): PRIVATE_BUILD_EXECUTABLE := $(cmd-build-executable)
 $(LOCAL_BUILT_MODULE): $(LOCAL_OBJECTS)
 	@ $(HOST_ECHO) "Executable     : $(PRIVATE_NAME)"
 	$(hide) $(PRIVATE_BUILD_EXECUTABLE)
diff --git a/build/core/build-shared-library.mk b/build/core/build-shared-library.mk
index 159aebb..f2e98f8 100644
--- a/build/core/build-shared-library.mk
+++ b/build/core/build-shared-library.mk
@@ -27,7 +27,7 @@
 # we are building target objects
 my := TARGET_
 
-$(call handle-module-filename,lib,.so)
+$(call handle-module-filename,lib,$(TARGET_SONAME_EXTENSION))
 $(call handle-module-built)
 
 LOCAL_MODULE_CLASS := SHARED_LIBRARY
diff --git a/build/core/build-static-library.mk b/build/core/build-static-library.mk
index cab3758..be30e74 100644
--- a/build/core/build-static-library.mk
+++ b/build/core/build-static-library.mk
@@ -26,7 +26,7 @@
 # we are building target objects
 my := TARGET_
 
-$(call handle-module-filename,lib,.a)
+$(call handle-module-filename,lib,$(TARGET_LIB_EXTENSION))
 $(call handle-module-built)
 
 LOCAL_MODULE_CLASS := STATIC_LIBRARY
diff --git a/build/core/default-build-commands.mk b/build/core/default-build-commands.mk
index 1f1c230..d31bc60 100644
--- a/build/core/default-build-commands.mk
+++ b/build/core/default-build-commands.mk
@@ -93,7 +93,7 @@
 # when applied to static libraries or object files.
 cmd-strip = $(PRIVATE_STRIP) --strip-unneeded $(call host-path,$1)
 
-TARGET_LIBGCC = $(shell $(TARGET_CC) -print-libgcc-file-name)
+TARGET_LIBGCC = -lgcc
 TARGET_LDLIBS := -lc -lm
 
 #
@@ -123,3 +123,7 @@
 TARGET_ARFLAGS := crs
 
 TARGET_STRIP    = $(TOOLCHAIN_PREFIX)strip
+
+TARGET_OBJ_EXTENSION := .o
+TARGET_LIB_EXTENSION := .a
+TARGET_SONAME_EXTENSION := .so
diff --git a/build/core/definitions-graph.mk b/build/core/definitions-graph.mk
new file mode 100644
index 0000000..6652a1f
--- /dev/null
+++ b/build/core/definitions-graph.mk
@@ -0,0 +1,523 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Definitions of various graph-related generic functions, used by
+# ndk-build internally.
+#
+
+# Coding style note:
+#
+# All internal variables in this file begin with '_ndk_mod_'
+# All internal functions in this file begin with '-ndk-mod-'
+#
+
+# Set this to true if you want to debug the functions here.
+_ndk_mod_debug := $(if $(NDK_DEBUG_MODULES),true)
+_ndk_topo_debug := $(if $(NDK_DEBUG_TOPO),true)
+
+# Use $(call -ndk-mod-debug,<message>) to print a debug message only
+# if _ndk_mod_debug is set to 'true'. Useful for debugging the functions
+# available here.
+#
+ifeq (true,$(_ndk_mod_debug))
+-ndk-mod-debug = $(info $1)
+else
+-ndk-mod-debug := $(empty)
+endif
+
+ifeq (true,$(_ndk_topo_debug))
+-ndk-topo-debug = $(info $1)
+else
+-ndk-topo-debug = $(empty)
+endif
+
+#######################################################################
+# Filter a list of module with a predicate function
+# $1: list of module names.
+# $2: predicate function, will be called with $(call $2,<name>), if the
+#     result is not empty, <name> will be added to the result.
+# Out: subset of input list, where each item passes the predicate.
+#######################################################################
+-ndk-mod-filter = $(strip \
+    $(foreach _ndk_mod_filter_n,$1,\
+        $(if $(call $2,$(_ndk_mod_filter_n)),$(_ndk_mod_filter_n))\
+    ))
+
+-test-ndk-mod-filter = \
+    $(eval -local-func = $$(call seq,foo,$$1))\
+    $(call test-expect,,$(call -ndk-mod-filter,,-local-func))\
+    $(call test-expect,foo,$(call -ndk-mod-filter,foo,-local-func))\
+    $(call test-expect,foo,$(call -ndk-mod-filter,foo bar,-local-func))\
+    $(call test-expect,foo foo,$(call -ndk-mod-filter,aaa foo bar foo,-local-func))\
+    $(eval -local-func = $$(call sne,foo,$$1))\
+    $(call test-expect,,$(call -ndk-mod-filter,,-local-func))\
+    $(call test-expect,,$(call -ndk-mod-filter,foo,-local-func))\
+    $(call test-expect,bar,$(call -ndk-mod-filter,foo bar,-local-func))\
+    $(call test-expect,aaa bar,$(call -ndk-mod-filter,aaa foo bar,-local-func))
+
+
+#######################################################################
+# Filter out a list of modules with a predicate function
+# $1: list of module names.
+# $2: predicate function, will be called with $(call $2,<name>), if the
+#     result is not empty, <name> will be added to the result.
+# Out: subset of input list, where each item doesn't pass the predicate.
+#######################################################################
+-ndk-mod-filter-out = $(strip \
+    $(foreach _ndk_mod_filter_n,$1,\
+        $(if $(call $2,$(_ndk_mod_filter_n)),,$(_ndk_mod_filter_n))\
+    ))
+
+-test-ndk-mod-filter-out = \
+    $(eval -local-func = $$(call seq,foo,$$1))\
+    $(call test-expect,,$(call -ndk-mod-filter-out,,-local-func))\
+    $(call test-expect,,$(call -ndk-mod-filter-out,foo,-local-func))\
+    $(call test-expect,bar,$(call -ndk-mod-filter-out,foo bar,-local-func))\
+    $(call test-expect,aaa bar,$(call -ndk-mod-filter-out,aaa foo bar foo,-local-func))\
+    $(eval -local-func = $$(call sne,foo,$$1))\
+    $(call test-expect,,$(call -ndk-mod-filter-out,,-local-func))\
+    $(call test-expect,foo,$(call -ndk-mod-filter-out,foo,-local-func))\
+    $(call test-expect,foo,$(call -ndk-mod-filter-out,foo bar,-local-func))\
+    $(call test-expect,foo foo,$(call -ndk-mod-filter-out,aaa foo bar foo,-local-func))
+
+
+#######################################################################
+# Find the first item in a list that checks a valid predicate.
+# $1: list of names.
+# $2: predicate function, will be called with $(call $2,<name>), if the
+#     result is not empty, <name> will be added to the result.
+# Out: subset of input list.
+#######################################################################
+-ndk-mod-find-first = $(firstword $(call -ndk-mod-filter,$1,$2))
+
+-test-ndk-mod-find-first.empty = \
+    $(eval -local-pred = $$(call seq,foo,$$1))\
+    $(call test-expect,,$(call -ndk-mod-find-first,,-local-pred))\
+    $(call test-expect,,$(call -ndk-mod-find-first,bar,-local-pred))
+
+-test-ndk-mod-find-first.simple = \
+    $(eval -local-pred = $$(call seq,foo,$$1))\
+    $(call test-expect,foo,$(call -ndk-mod-find-first,foo,-local-pred))\
+    $(call test-expect,foo,$(call -ndk-mod-find-first,aaa foo bar,-local-pred))\
+    $(call test-expect,foo,$(call -ndk-mod-find-first,aaa foo foo bar,-local-pred))
+
+########################################################################
+# Many tree walking operations require setting a 'visited' flag on
+# specific graph nodes. The following helper functions help implement
+# this while hiding details to the callers.
+#
+# Technical note:
+#  _ndk_mod_tree_visited.<name> will be 'true' if the node was visited,
+#  or empty otherwise.
+#
+#  _ndk_mod_tree_visitors lists all visited nodes, used to clean all
+#  _ndk_mod_tree_visited.<name> variables in -ndk-mod-tree-setup-visit.
+#
+#######################################################################
+
+# Call this before tree traversal.
+-ndk-mod-tree-setup-visit = \
+    $(foreach _ndk_mod_tree_visitor,$(_ndk_mod_tree_visitors),\
+        $(eval _ndk_mod_tree_visited.$$(_ndk_mod_tree_visitor) :=))\
+    $(eval _ndk_mod_tree_visitors :=)
+
+# Returns non-empty if a node was visited.
+-ndk-mod-tree-is-visited = \
+    $(_ndk_mod_tree_visited.$1)
+
+# Set the visited state of a node to 'true'
+-ndk-mod-tree-set-visited = \
+    $(eval _ndk_mod_tree_visited.$1 := true)\
+    $(eval _ndk_mod_tree_visitors += $1)
+
+########################################################################
+# Many graph walking operations require a work queue and computing
+# dependencies / children nodes. Here are a few helper functions that
+# can be used to make their code clearer. This uses a few global
+# variables that should be defined as follows during the operation:
+#
+#  _ndk_mod_module     current graph node name.
+#  _ndk_mod_wq         current node work queue.
+#  _ndk_mod_list       current result (list of nodes).
+#  _ndk_mod_depends    current graph node's children.
+#                      you must call -ndk-mod-get-depends to set this.
+#
+#######################################################################
+
+# Pop first item from work-queue into _ndk_mod_module.
+-ndk-mod-pop-first = \
+    $(eval _ndk_mod_module := $$(call first,$$(_ndk_mod_wq)))\
+    $(eval _ndk_mod_wq     := $$(call rest,$$(_ndk_mod_wq)))
+
+-test-ndk-mod-pop-first = \
+    $(eval _ndk_mod_wq := A B C)\
+    $(call -ndk-mod-pop-first)\
+    $(call test-expect,A,$(_ndk_mod_module))\
+    $(call test-expect,B C,$(_ndk_mod_wq))\
+
+
+# Push list of items at the back of the work-queue.
+-ndk-mod-push-back = \
+    $(eval _ndk_mod_wq := $(strip $(_ndk_mod_wq) $1))
+
+-test-ndk-mod-push-back = \
+  $(eval _ndk_mod_wq := A B C)\
+  $(call -ndk-mod-push-back, D    E)\
+  $(call test-expect,A B C D E,$(_ndk_mod_wq))
+
+# Set _ndk_mod_depends to the direct dependencies of _ndk_mod_module
+-ndk-mod-get-depends = \
+    $(eval _ndk_mod_depends := $$(call $$(_ndk_mod_deps_func),$$(_ndk_mod_module)))
+
+# Set _ndk_mod_depends to the direct dependencies of _ndk_mod_module that
+# are not already in _ndk_mod_list.
+-ndk-mod-get-new-depends = \
+    $(call -ndk-mod-get-depends)\
+    $(eval _ndk_mod_depends := $$(filter-out $$(_ndk_mod_list),$$(_ndk_mod_depends)))
+
+##########################################################################
+# Compute the transitive closure
+# $1: list of modules.
+# $2: dependency function, $(call $2,<module>) should return all the
+#     module that <module> depends on.
+# Out: transitive closure of all modules from those in $1. Always includes
+#      the modules in $1. Order is random.
+#
+# Implementation note:
+#   we use the -ndk-mod-tree-xxx functions to flag 'visited' nodes
+#   in the graph. A node is visited once it has been put into the work
+#   queue. For each item in the work queue, get the dependencies and
+#   append all those that were not visited yet.
+#######################################################################
+-ndk-mod-get-closure = $(strip \
+    $(eval _ndk_mod_wq :=)\
+    $(eval _ndk_mod_list :=)\
+    $(eval _ndk_mod_deps_func := $2)\
+    $(call -ndk-mod-tree-setup-visit)\
+    $(foreach _ndk_mod_module,$1,\
+        $(call -ndk-mod-closure-visit,$(_ndk_mod_module))\
+    )\
+    $(call -ndk-mod-closure-recursive)\
+    $(eval _ndk_mod_deps :=)\
+    $(_ndk_mod_list)\
+    )
+
+# Used internally to visit a new node during -ndk-mod-get-closure.
+# This appends the node to the work queue, and set its 'visit' flag.
+-ndk-mod-closure-visit = \
+    $(call -ndk-mod-push-back,$1)\
+    $(call -ndk-mod-tree-set-visited,$1)
+
+-ndk-mod-closure-recursive = \
+    $(call -ndk-mod-pop-first)\
+    $(eval _ndk_mod_list += $$(_ndk_mod_module))\
+    $(call -ndk-mod-get-depends)\
+    $(foreach _ndk_mod_dep,$(_ndk_mod_depends),\
+        $(if $(call -ndk-mod-tree-is-visited,$(_ndk_mod_dep)),,\
+        $(call -ndk-mod-closure-visit,$(_ndk_mod_dep))\
+        )\
+    )\
+    $(if $(_ndk_mod_wq),$(call -ndk-mod-closure-recursive))
+
+-test-ndk-mod-get-closure.empty = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(call test-expect,,$(call -ndk-mod-get-closure,,-local-deps))
+
+-test-ndk-mod-get-closure.single = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends :=)\
+    $(call test-expect,A,$(call -ndk-mod-get-closure,A,-local-deps))
+
+-test-ndk-mod-get-closure.double = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends := B)\
+    $(eval B_depends :=)\
+    $(call test-expect,A B,$(call -ndk-mod-get-closure,A,-local-deps))
+
+-test-ndk-mod-get-closure.circular-deps = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends := B)\
+    $(eval B_depends := C)\
+    $(eval C_depends := A)\
+    $(call test-expect,A B C,$(call -ndk-mod-get-closure,A,-local-deps))
+
+-test-ndk-mod-get-closure.ABCDE = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends := B C)\
+    $(eval B_depends := D)\
+    $(eval C_depends := D E)\
+    $(eval D_depends :=)\
+    $(eval E_depends :=)\
+    $(call test-expect,A B C D E,$(call -ndk-mod-get-closure,A,-local-deps))
+
+
+#########################################################################
+# For topological sort, we need to count the number of incoming edges
+# in each graph node. The following helper functions implement this and
+# hide implementation details.
+#
+# Count the number of incoming edges for each node during topological
+# sort with a string of xxxxs. I.e.:
+#  0 edge  -> ''
+#  1 edge  -> 'x'
+#  2 edges -> 'xx'
+#  3 edges -> 'xxx'
+#  etc.
+#########################################################################
+
+# zero the incoming edge counter for module $1
+-ndk-mod-topo-zero-incoming = \
+    $(eval _ndk_mod_topo_incoming.$1 :=)
+
+# increment the incoming edge counter for module $1
+-ndk-mod-topo-increment-incoming = \
+    $(eval _ndk_mod_topo_incoming.$1 := $$(_ndk_mod_topo_incoming.$1)x)
+
+# decrement the incoming edge counter for module $1
+-ndk-mod-topo-decrement-incoming = \
+    $(eval _ndk_mod_topo_incoming.$1 := $$(_ndk_mod_topo_incoming.$1:%x=%))
+
+# return non-empty if the module $1's incoming edge counter is > 0
+-ndk-mod-topo-has-incoming = $(_ndk_mod_topo_incoming.$1)
+
+# Find first node in a list that has zero incoming edges.
+# $1: list of nodes
+# Out: first node that has zero incoming edges, or empty.
+-ndk-mod-topo-find-first-zero-incoming = $(firstword $(call -ndk-mod-filter-out,$1,-ndk-mod-topo-has-incoming))
+
+# Only use for debugging:
+-ndk-mod-topo-dump-count = \
+    $(foreach _ndk_mod_module,$1,\
+        $(info .. $(_ndk_mod_module) incoming='$(_ndk_mod_topo_incoming.$(_ndk_mod_module))'))
+
+
+
+#########################################################################
+# Return the topologically ordered closure of all nodes from a top-level
+# one. This means that a node A, in the result, will always appear after
+# node B if A depends on B. Assumes that the graph is a DAG (if there are
+# circular dependencies, this property cannot be guaranteed, but at least
+# the function should not loop infinitely).
+#
+# $1: top-level node name.
+# $2: dependency function, i.e. $(call $2,<name>) returns the children
+#     nodes for <name>.
+# Return: list of nodes, include $1, which will always be the first.
+#########################################################################
+-ndk-mod-get-topo-list = $(strip \
+    $(eval _ndk_mod_top_module := $1)\
+    $(eval _ndk_mod_deps_func := $2)\
+    $(eval _ndk_mod_nodes := $(call -ndk-mod-get-closure,$1,$2))\
+    $(call -ndk-mod-topo-count,$(_ndk_mod_nodes))\
+    $(eval _ndk_mod_list :=)\
+    $(eval _ndk_mod_wq := $(call -ndk-mod-topo-find-first-zero-incoming,$(_ndk_mod_nodes)))\
+    $(if $(_ndk_mod_wq),\
+        $(call -ndk-mod-topo-sort)\
+        $(_ndk_mod_list)\
+    ,\
+        $(_ndk_mod_nodes)\
+    ))
+
+# Given a closure list of nodes, count their incoming edges.
+# $1: list of nodes, must be a graph closure.
+-ndk-mod-topo-count = \
+    $(foreach _ndk_mod_module,$1,\
+        $(call -ndk-mod-topo-zero-incoming,$(_ndk_mod_module)))\
+    $(foreach _ndk_mod_module,$1,\
+        $(call -ndk-mod-get-depends)\
+        $(foreach _ndk_mod_dep,$(_ndk_mod_depends),\
+        $(call -ndk-mod-topo-increment-incoming,$(_ndk_mod_dep))\
+        )\
+    )
+
+-ndk-mod-topo-sort = \
+    $(call -ndk-topo-debug,-ndk-mod-topo-sort: wq='$(_ndk_mod_wq)' list='$(_ndk_mod_list)')\
+    $(call -ndk-mod-pop-first)\
+    $(if $(_ndk_mod_module),\
+        $(eval _ndk_mod_list += $(_ndk_mod_module))\
+        $(call -ndk-mod-topo-decrement-incoming,$(_ndk_mod_module))\
+        $(call -ndk-mod-get-depends)\
+        $(call -ndk-topo-debug,-ndk-mod-topo-sort:   deps='$(_ndk_mod_depends)')\
+        $(foreach _ndk_mod_dep,$(_ndk_mod_depends),\
+            $(call -ndk-mod-topo-decrement-incoming,$(_ndk_mod_dep))\
+            $(if $(call -ndk-mod-topo-has-incoming,$(_ndk_mod_dep)),,\
+                $(call -ndk-mod-push-back,$(_ndk_mod_dep))\
+            )\
+        )\
+        $(call -ndk-mod-topo-sort)\
+    )
+
+
+-test-ndk-mod-get-topo-list.empty = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(call test-expect,,$(call -ndk-mod-get-topo-list,,-local-deps))
+
+-test-ndk-mod-get-topo-list.single = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends :=)\
+    $(call test-expect,A,$(call -ndk-mod-get-topo-list,A,-local-deps))
+
+-test-ndk-mod-get-topo-list.no-infinite-loop = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends := B)\
+    $(eval B_depends := C)\
+    $(eval C_depends := A)\
+    $(call test-expect,A B C,$(call -ndk-mod-get-topo-list,A,-local-deps))
+
+-test-ndk-mod-get-topo-list.ABC = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends := B C)\
+    $(eval B_depends :=)\
+    $(eval C_depends := B)\
+    $(call test-expect,A C B,$(call -ndk-mod-get-topo-list,A,-local-deps))
+
+-test-ndk-mod-get-topo-list.ABCD = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends := B C)\
+    $(eval B_depends := D)\
+    $(eval C_depends := B)\
+    $(eval D_depends :=)\
+    $(call test-expect,A C B D,$(call -ndk-mod-get-topo-list,A,-local-deps))
+
+#########################################################################
+# Return the topologically ordered closure of all dependencies from a
+# top-level node.
+#
+# $1: top-level node name.
+# $2: dependency function, i.e. $(call $2,<name>) returns the children
+#     nodes for <name>.
+# Return: list of nodes, include $1, which will never be included.
+#########################################################################
+-ndk-mod-get-topological-depends = $(call rest,$(call -ndk-mod-get-topo-list,$1,$2))
+
+-test-ndk-mod-get-topological-depends.simple = \
+    $(eval -local-get-deps = $$($$1_depends))\
+    $(eval A_depends := B)\
+    $(eval B_depends :=)\
+    $(eval topo_deps := $$(call -ndk-mod-get-topological-depends,A,-local-get-deps))\
+    $(call test-expect,B,$(topo_deps),topo dependencies)
+
+-test-ndk-mod-get-topological-depends.ABC = \
+    $(eval -local-get-deps = $$($$1_depends))\
+    $(eval A_depends := B C)\
+    $(eval B_depends :=)\
+    $(eval C_depends := B)\
+    $(eval bfs_deps := $$(call -ndk-mod-get-bfs-depends,A,-local-get-deps))\
+    $(eval topo_deps := $$(call -ndk-mod-get-topological-depends,A,-local-get-deps))\
+    $(call test-expect,B C,$(bfs_deps),dfs dependencies)\
+    $(call test-expect,C B,$(topo_deps),topo dependencies)
+
+#########################################################################
+# Return breadth-first walk of a graph, starting from an arbitrary
+# node.
+#
+# This performs a breadth-first walk of the graph and will return a
+# list of nodes. Note that $1 will always be the first in the list.
+#
+# $1: root node name.
+# $2: dependency function, i.e. $(call $2,<name>) returns the nodes
+#     that <name> depends on.
+# Result: list of dependent modules, $1 will be part of it.
+#########################################################################
+-ndk-mod-get-bfs-list = $(strip \
+    $(eval _ndk_mod_wq := $(call strip-lib-prefix,$1)) \
+    $(eval _ndk_mod_deps_func := $2)\
+    $(eval _ndk_mod_list :=)\
+    $(call -ndk-mod-tree-setup-visit)\
+    $(call -ndk-mod-tree-set-visited,$(_ndk_mod_wq))\
+    $(call -ndk-mod-bfs-recursive) \
+    $(_ndk_mod_list))
+
+# Recursive function used to perform a depth-first scan.
+# Must initialize _ndk_mod_list, _ndk_mod_field, _ndk_mod_wq
+# before calling this.
+-ndk-mod-bfs-recursive = \
+    $(call -ndk-mod-debug,-ndk-mod-bfs-recursive wq='$(_ndk_mod_wq)' list='$(_ndk_mod_list)' visited='$(_ndk_mod_tree_visitors)')\
+    $(call -ndk-mod-pop-first)\
+    $(eval _ndk_mod_list += $$(_ndk_mod_module))\
+    $(call -ndk-mod-get-depends)\
+    $(call -ndk-mod-debug,.  node='$(_ndk_mod_module)' deps='$(_ndk_mod_depends)')\
+    $(foreach _ndk_mod_child,$(_ndk_mod_depends),\
+        $(if $(call -ndk-mod-tree-is-visited,$(_ndk_mod_child)),,\
+            $(call -ndk-mod-tree-set-visited,$(_ndk_mod_child))\
+            $(call -ndk-mod-push-back,$(_ndk_mod_child))\
+        )\
+    )\
+    $(if $(_ndk_mod_wq),$(call -ndk-mod-bfs-recursive))
+
+-test-ndk-mod-get-bfs-list.empty = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(call test-expect,,$(call -ndk-mod-get-bfs-list,,-local-deps))
+
+-test-ndk-mod-get-bfs-list.A = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends :=)\
+    $(call test-expect,A,$(call -ndk-mod-get-bfs-list,A,-local-deps))
+
+-test-ndk-mod-get-bfs-list.ABCDEF = \
+    $(eval -local-deps = $$($$1_depends))\
+    $(eval A_depends := B C)\
+    $(eval B_depends := D E)\
+    $(eval C_depends := F E)\
+    $(eval D_depends :=)\
+    $(eval E_depends :=)\
+    $(eval F_depends :=)\
+    $(call test-expect,A B C D E F,$(call -ndk-mod-get-bfs-list,A,-local-deps))
+
+#########################################################################
+# Return breadth-first walk of a graph, starting from an arbitrary
+# node.
+#
+# This performs a breadth-first walk of the graph and will return a
+# list of nodes. Note that $1 will _not_ be part of the list.
+#
+# $1: root node name.
+# $2: dependency function, i.e. $(call $2,<name>) returns the nodes
+#     that <name> depends on.
+# Result: list of dependent modules, $1 will not be part of it.
+#########################################################################
+-ndk-mod-get-bfs-depends = $(call rest,$(call -ndk-mod-get-bfs-list,$1,$2))
+
+-test-ndk-mod-get-bfs-depends.simple = \
+    $(eval -local-deps-func = $$($$1_depends))\
+    $(eval A_depends := B)\
+    $(eval B_depends :=)\
+    $(eval deps := $$(call -ndk-mod-get-bfs-depends,A,-local-deps-func))\
+    $(call test-expect,B,$(deps))
+
+-test-ndk-mod-get-bfs-depends.ABC = \
+    $(eval -local-deps-func = $$($$1_depends))\
+    $(eval A_depends := B C)\
+    $(eval B_depends :=)\
+    $(eval C_depends := B)\
+    $(eval deps := $$(call -ndk-mod-get-bfs-depends,A,-local-deps-func))\
+    $(call test-expect,B C,$(deps))\
+
+-test-ndk-mod-get-bfs-depends.ABCDE = \
+    $(eval -local-deps-func = $$($$1_depends))\
+    $(eval A_depends := B C)\
+    $(eval B_depends := D)\
+    $(eval C_depends := D E F)\
+    $(eval D_depends :=)\
+    $(eval E_depends :=)\
+    $(eval F_depends :=)\
+    $(eval deps := $$(call -ndk-mod-get-bfs-depends,A,-local-deps-func))\
+    $(call test-expect,B C D E F,$(deps))\
+
+-test-ndk-mod-get-bfs-depends.loop = \
+    $(eval -local-deps-func = $$($$1_depends))\
+    $(eval A_depends := B)\
+    $(eval B_depends := A)\
+    $(eval deps := $$(call -ndk-mod-get-bfs-depends,A,-local-deps-func))\
+    $(call test-expect,B,$(deps))
diff --git a/build/core/definitions-host.mk b/build/core/definitions-host.mk
new file mode 100644
index 0000000..c215687
--- /dev/null
+++ b/build/core/definitions-host.mk
@@ -0,0 +1,136 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# These definitions contain a few host-specific functions. I.e. they are
+# typically used to generate shell commands during the build and their
+# implementation will depend on the value of the HOST_OS variable.
+#
+
+# -----------------------------------------------------------------------------
+# Function : host-path
+# Arguments: 1: file path
+# Returns  : file path, as understood by the host file system
+# Usage    : $(call host-path,<path>)
+# Rationale: This function is used to translate Cygwin paths into
+#            Cygwin-specific ones. On other platforms, it will just
+#            return its argument.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),cygwin)
+host-path = $(if $(strip $1),$(call cygwin-to-host-path,$1))
+else
+host-path = $1
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-rm
+# Arguments: 1: list of files
+# Usage    : $(call host-rm,<files>)
+# Rationale: This function expands to the host-specific shell command used
+#            to remove some files.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-rm = \
+    $(eval __host_rm_files := $(foreach __host_rm_file,$1,$(subst /,\,$(wildcard $(__host_rm_file)))))\
+    $(if $(__host_rm_files),del /f/q $(__host_rm_files) >NUL 2>NUL)
+else
+host-rm = rm -f $1
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-rmdir
+# Arguments: 1: list of files or directories
+# Usage    : $(call host-rm,<files>)
+# Rationale: This function expands to the host-specific shell command used
+#            to remove some files _and_ directories.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-rmdir = \
+    $(eval __host_rmdir_files := $(foreach __host_rmdir_file,$1,$(subst /,\,$(wildcard $(__host_rmdir_file)))))\
+    $(if $(__host_rmdir_files),del /f/s/q $(__host_rmdir_files) >NUL 2>NUL)
+else
+host-rmdir = rm -rf $1
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-mkdir
+# Arguments: 1: directory path
+# Usage    : $(call host-mkdir,<path>
+# Rationale: This function expands to the host-specific shell command used
+#            to create a path if it doesn't exist.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-mkdir = md $(subst /,\,"$1") >NUL 2>NUL || rem
+else
+host-mkdir = mkdir -p $1
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-cp
+# Arguments: 1: source file
+#            2: target file
+# Usage    : $(call host-cp,<src-file>,<dst-file>)
+# Rationale: This function expands to the host-specific shell command used
+#            to copy a single file
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-cp = copy /b/y $(subst /,\,"$1" "$2") > NUL
+else
+host-cp = cp -f $1 $2
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-install
+# Arguments: 1: source file
+#            2: target file
+# Usage    : $(call host-install,<src-file>,<dst-file>)
+# Rationale: This function expands to the host-specific shell command used
+#            to install a file or directory, while preserving its timestamps
+#            (if possible).
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-install = copy /b/y $(subst /,\,"$1" "$2") > NUL
+else
+host-install = install -p $1 $2
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-c-includes
+# Arguments: 1: list of file paths (e.g. "foo bar")
+# Returns  : list of include compiler options (e.g. "-Ifoo -Ibar")
+# Usage    : $(call host-c-includes,<paths>)
+# Rationale: This function is used to translate Cygwin paths into
+#            Cygwin-specific ones. On other platforms, it will just
+#            return its argument.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),cygwin)
+host-c-includes = $(patsubst %,-I%,$(call host-path,$1))
+else
+host-c-includes = $(1:%=-I%)
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-copy-if-differ
+# Arguments: 1: source file
+#            2: destination file
+# Usage    : $(call host-copy-if-differ,<src-file>,<dst-file>)
+# Rationale: This function copy source file to destination file if contents are
+#            different.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-copy-if-differ = $(HOST_CMP) -s $1 $2 > NUL || copy /b/y $(subst /,\,"$1" "$2") > NUL
+else
+host-copy-if-differ = $(HOST_CMP) -s $1 $2 > /dev/null 2>&1 || cp -f $1 $2
+endif
+
diff --git a/build/core/definitions-tests.mk b/build/core/definitions-tests.mk
new file mode 100644
index 0000000..074036b
--- /dev/null
+++ b/build/core/definitions-tests.mk
@@ -0,0 +1,106 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Definitions for the Android NDK build system's internal unit tests.
+#
+
+#
+# A function which names begin with -test- (e.g. -test-foo) is assumed
+# to be an internal unit test. It will be run automatically by ndk-build
+# if NDK_UNIT_TESTS is defined in your environment.
+#
+# Each test should call one of the following functions that will
+# register a failure:
+#
+#   $(call test-expect,<expected-value>,<actual-value>)
+#
+#      This will check that <actual-value> is equal to <expected-value>.
+#      If not, this will print an error message and increment the failure
+#      counter.
+#
+#   $(call test-assert,<expected-value>,<actual-value>)
+#
+#      This is similar to test-expect, though it will abort the program
+#      immediately after displaying an error message.
+#
+# Here's an example that checks that the 'filter' function works correctly:
+#
+#   -test-filter = \
+#     $(call test-expect,foo,$(filter bar,foo bar))
+#
+#
+
+-ndk-test-start = \
+  $(eval _test_name := $1)\
+  $(eval _test_list += $1)\
+  $(eval _test_failed :=)\
+  $(info [$1  RUN])
+
+# End current unit test.
+#
+-ndk-test-end = \
+  $(if $(_test_failed),\
+    $(info [$(_test_name) FAIL])$(error Aborting)\
+    $(eval _test_failures += $$(_test_name))\
+  ,\
+    $(info [$(_test_name)   OK])\
+  )
+
+# Define NDK_UNIT_TESTS to 2 to dump each test-expect/assert check.
+#
+ifeq (2,$(NDK_UNIT_TESTS))
+-ndk-test-log = $(info .  $(_test_name): $1)
+else
+-ndk-test-log = $(empty)
+endif
+
+test-expect = \
+  $(call -ndk-test-log,expect '$2' == '$1')\
+  $(if $(call sne,$1,$2),\
+    $(info ERROR <$(_test_name)>:$3)\
+    $(info .  expected value:'$1')\
+    $(info .  actual value:  '$2')\
+    $(eval _test_failed := true)\
+  )
+
+test-assert = \
+  $(call -ndk-test-log,assert '$2' == '$1')\
+  $(if $(call sne,$1,$2),\
+    $(info ASSERT <$(_test_name)>:$3)\
+    $(info .  expected value:'$1')\
+    $(info .  actual value:  '$2')\
+    $(eval _test_failed := true)\
+    $(error Aborting.)\
+  )
+
+# Run all the tests, i.e. all functions that are defined with a -test-
+# prefix will be called now in succession.
+ndk-run-all-tests = \
+  $(info ================= STARTING NDK-BUILD UNIT TESTS =================)\
+  $(eval _test_list :=)\
+  $(eval _test_failures :=)\
+  $(foreach _test,$(filter -test-%,$(.VARIABLES)),\
+    $(call -ndk-test-start,$(_test))\
+    $(call $(_test))\
+    $(call -ndk-test-end)\
+  )\
+  $(eval _test_count := $$(words $$(_test_list)))\
+  $(eval _test_fail_count := $$(words $$(_test_failures)))\
+  $(if $(_test_failures),\
+    $(info @@@@@@@@@@@ FAILED $(_test_fail_count) of $(_test_count) NDK-BUILD UNIT TESTS @@@@@@@)\
+    $(foreach _test_name,$(_test_failures),\
+      $(info .  $(_test_name)))\
+  ,\
+    $(info =================== PASSED $(_test_count) NDK-BUILD UNIT TESTS =================)\
+  )
diff --git a/build/core/definitions-utils.mk b/build/core/definitions-utils.mk
new file mode 100644
index 0000000..0f24404
--- /dev/null
+++ b/build/core/definitions-utils.mk
@@ -0,0 +1,170 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Common utility functions.
+#
+# NOTE: All the functions here should be purely functional, i.e. avoid
+#       using global variables or depend on the file system / environment
+#       variables. This makes testing easier.
+
+# -----------------------------------------------------------------------------
+# Macro    : empty
+# Returns  : an empty macro
+# Usage    : $(empty)
+# -----------------------------------------------------------------------------
+empty :=
+
+# -----------------------------------------------------------------------------
+# Macro    : space
+# Returns  : a single space
+# Usage    : $(space)
+# -----------------------------------------------------------------------------
+space  := $(empty) $(empty)
+
+space4 := $(space)$(space)$(space)$(space)
+
+# -----------------------------------------------------------------------------
+# Function : remove-duplicates
+# Arguments: a list
+# Returns  : the list with duplicate items removed, order is preserved.
+# Usage    : $(call remove-duplicates, <LIST>)
+# Note     : This is equivalent to the 'uniq' function provided by GMSL,
+#            however this implementation is non-recursive and *much*
+#            faster. It will also not explode the stack with a lot of
+#            items like 'uniq' does.
+# -----------------------------------------------------------------------------
+remove-duplicates = $(strip \
+  $(eval __uniq_ret :=) \
+  $(foreach __uniq_item,$1,\
+    $(if $(findstring $(__uniq_item),$(__uniq_ret)),,\
+      $(eval __uniq_ret += $(__uniq_item))\
+    )\
+  )\
+  $(__uniq_ret))
+
+-test-remove-duplicates = \
+  $(call test-expect,,$(call remove-duplicates))\
+  $(call test-expect,foo bar,$(call remove-duplicates,foo bar))\
+  $(call test-expect,foo bar,$(call remove-duplicates,foo bar foo bar))\
+  $(call test-expect,foo bar,$(call remove-duplicates,foo foo bar bar bar))
+
+# -----------------------------------------------------------------------------
+# Function : clear-vars
+# Arguments: 1: list of variable names
+#            2: file where the variable should be defined
+# Returns  : None
+# Usage    : $(call clear-vars, VAR1 VAR2 VAR3...)
+# Rationale: Clears/undefines all variables in argument list
+# -----------------------------------------------------------------------------
+clear-vars = $(foreach __varname,$1,$(eval $(__varname) := $(empty)))
+
+# -----------------------------------------------------------------------------
+# Function : filter-by
+# Arguments: 1: list
+#            2: predicate function, will be called as $(call $2,<name>)
+#               and it this returns a non-empty value, then <name>
+#               will be appended to the result.
+# Returns  : elements of $1 that satisfy the predicate function $2
+# -----------------------------------------------------------------------------
+filter-by = $(strip \
+  $(foreach __filter_by_n,$1,\
+    $(if $(call $2,$(__filter_by_n)),$(__filter_by_n))))
+
+-test-filter-by = \
+    $(eval -local-func = $$(call seq,foo,$$1))\
+    $(call test-expect,,$(call filter-by,,-local-func))\
+    $(call test-expect,foo,$(call filter-by,foo,-local-func))\
+    $(call test-expect,foo,$(call filter-by,foo bar,-local-func))\
+    $(call test-expect,foo foo,$(call filter-by,aaa foo bar foo,-local-func))\
+    $(eval -local-func = $$(call sne,foo,$$1))\
+    $(call test-expect,,$(call filter-by,,-local-func))\
+    $(call test-expect,,$(call filter-by,foo,-local-func))\
+    $(call test-expect,bar,$(call filter-by,foo bar,-local-func))\
+    $(call test-expect,aaa bar,$(call filter-by,aaa foo bar,-local-func))
+
+# -----------------------------------------------------------------------------
+# Function : filter-out-by
+# Arguments: 1: list
+#            2: predicate function, will be called as $(call $2,<name>)
+#               and it this returns an empty value, then <name>
+#               will be appended to the result.
+# Returns  : elements of $1 that do not satisfy the predicate function $2
+# -----------------------------------------------------------------------------
+filter-out-by = $(strip \
+  $(foreach __filter_out_by_n,$1,\
+    $(if $(call $2,$(__filter_out_by_n)),,$(__filter_out_by_n))))
+
+-test-filter-out-by = \
+    $(eval -local-func = $$(call seq,foo,$$1))\
+    $(call test-expect,,$(call filter-out-by,,-local-func))\
+    $(call test-expect,,$(call filter-out-by,foo,-local-func))\
+    $(call test-expect,bar,$(call filter-out-by,foo bar,-local-func))\
+    $(call test-expect,aaa bar,$(call filter-out-by,aaa foo bar foo,-local-func))\
+    $(eval -local-func = $$(call sne,foo,$$1))\
+    $(call test-expect,,$(call filter-out-by,,-local-func))\
+    $(call test-expect,foo,$(call filter-out-by,foo,-local-func))\
+    $(call test-expect,foo,$(call filter-out-by,foo bar,-local-func))\
+    $(call test-expect,foo foo,$(call filter-out-by,aaa foo bar foo,-local-func))
+
+# -----------------------------------------------------------------------------
+# Function : find-first
+# Arguments: 1: list
+#            2: predicate function, will be called as $(call $2,<name>).
+# Returns  : the first item of $1 that satisfies the predicate.
+# -----------------------------------------------------------------------------
+find-first = $(firstword $(call filter-by,$1,$2))
+
+-testfind-first.empty = \
+    $(eval -local-pred = $$(call seq,foo,$$1))\
+    $(call test-expect,,$(call find-first,,-local-pred))\
+    $(call test-expect,,$(call find-first,bar,-local-pred))
+
+-testfind-first.simple = \
+    $(eval -local-pred = $$(call seq,foo,$$1))\
+    $(call test-expect,foo,$(call find-first,foo,-local-pred))\
+    $(call test-expect,foo,$(call find-first,aaa foo bar,-local-pred))\
+    $(call test-expect,foo,$(call find-first,aaa foo foo bar,-local-pred))
+
+# -----------------------------------------------------------------------------
+# Function : parent-dir
+# Arguments: 1: path
+# Returns  : Parent dir or path of $1, with final separator removed.
+# -----------------------------------------------------------------------------
+parent-dir = $(patsubst %/,%,$(dir $(1:%/=%)))
+
+-test-parent-dir = \
+  $(call test-expect,,$(call parent-dir))\
+  $(call test-expect,.,$(call parent-dir,foo))\
+  $(call test-expect,foo,$(call parent-dir,foo/bar))\
+  $(call test-expect,foo,$(call parent-dir,foo/bar/))
+
+# -----------------------------------------------------------------------------
+# Strip any 'lib' prefix in front of a given string.
+#
+# Function : strip-lib-prefix
+# Arguments: 1: module name
+# Returns  : module name, without any 'lib' prefix if any
+# Usage    : $(call strip-lib-prefix,$(LOCAL_MODULE))
+# -----------------------------------------------------------------------------
+strip-lib-prefix = $(1:lib%=%)
+
+-test-strip-lib-prefix = \
+  $(call test-expect,,$(call strip-lib-prefix,))\
+  $(call test-expect,foo,$(call strip-lib-prefix,foo))\
+  $(call test-expect,foo,$(call strip-lib-prefix,libfoo))\
+  $(call test-expect,nolibfoo,$(call strip-lib-prefix,nolibfoo))\
+  $(call test-expect,foolib,$(call strip-lib-prefix,foolib))\
+  $(call test-expect,foo bar,$(call strip-lib-prefix,libfoo libbar))
+
diff --git a/build/core/definitions.mk b/build/core/definitions.mk
index 8b8d5a0..92ed684 100644
--- a/build/core/definitions.mk
+++ b/build/core/definitions.mk
@@ -18,69 +18,10 @@
 # We use the GNU Make Standard Library
 include $(NDK_ROOT)/build/gmsl/gmsl
 
-# If NDK_TRACE is enabled then calls to the library functions are
-# traced to stdout using warning messages with their arguments
-
-ifdef NDK_TRACE
-__ndk_tr1 = $(warning $0('$1'))
-__ndk_tr2 = $(warning $0('$1','$2'))
-__ndk_tr3 = $(warning $0('$1','$2','$3'))
-else
-__ndk_tr1 :=
-__ndk_tr2 :=
-__ndk_tr3 :=
-endif
-
-# -----------------------------------------------------------------------------
-# Macro    : empty
-# Returns  : an empty macro
-# Usage    : $(empty)
-# -----------------------------------------------------------------------------
-empty :=
-
-# -----------------------------------------------------------------------------
-# Macro    : space
-# Returns  : a single space
-# Usage    : $(space)
-# -----------------------------------------------------------------------------
-space  := $(empty) $(empty)
-
-space4 := $(space)$(space)$(space)$(space)
-
-# -----------------------------------------------------------------------------
-# Function : last2
-# Arguments: a list
-# Returns  : the penultimate (next-to-last) element of a list
-# Usage    : $(call last2, <LIST>)
-# -----------------------------------------------------------------------------
-last2 = $(word $(words $1), x $1)
-
-# -----------------------------------------------------------------------------
-# Function : last3
-# Arguments: a list
-# Returns  : the antepenultimate (second-next-to-last) element of a list
-# Usage    : $(call last3, <LIST>)
-# -----------------------------------------------------------------------------
-last3 = $(word $(words $1), x x $1)
-
-# -----------------------------------------------------------------------------
-# Function : remove-duplicates
-# Arguments: a list
-# Returns  : the list with duplicate items removed, order is preserved.
-# Usage    : $(call remove-duplicates, <LIST>)
-# Note     : This is equivalent to the 'uniq' function provided by GMSL,
-#            however this implementation is non-recursive and *much*
-#            faster. It will also not explode the stack with a lot of
-#            items like 'uniq' does.
-# -----------------------------------------------------------------------------
-remove-duplicates = $(strip \
-  $(eval __uniq_ret :=) \
-  $(foreach __uniq_item,$1,\
-    $(if $(findstring $(__uniq_item),$(__uniq_ret)),,\
-      $(eval __uniq_ret += $(__uniq_item))\
-    )\
-  )\
-  $(__uniq_ret))
+include $(BUILD_SYSTEM)/definitions-tests.mk
+include $(BUILD_SYSTEM)/definitions-utils.mk
+include $(BUILD_SYSTEM)/definitions-host.mk
+include $(BUILD_SYSTEM)/definitions-graph.mk
 
 # -----------------------------------------------------------------------------
 # Macro    : this-makefile
@@ -111,16 +52,6 @@
 )
 
 # -----------------------------------------------------------------------------
-# Function : clear-vars
-# Arguments: 1: list of variable names
-#            2: file where the variable should be defined
-# Returns  : None
-# Usage    : $(call clear-vars, VAR1 VAR2 VAR3...)
-# Rationale: Clears/undefines all variables in argument list
-# -----------------------------------------------------------------------------
-clear-vars = $(foreach __varname,$1,$(eval $(__varname) := $(empty)))
-
-# -----------------------------------------------------------------------------
 # Function : check-required-vars
 # Arguments: 1: list of variable names
 #            2: file where the variable(s) should be defined
@@ -140,122 +71,6 @@
 default-c++-extensions := .cc .cp .cxx .cpp .CPP .c++ .C
 
 # -----------------------------------------------------------------------------
-# Function : host-path
-# Arguments: 1: file path
-# Returns  : file path, as understood by the host file system
-# Usage    : $(call host-path,<path>)
-# Rationale: This function is used to translate Cygwin paths into
-#            Cygwin-specific ones. On other platforms, it will just
-#            return its argument.
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),cygwin)
-host-path = $(if $(strip $1),$(call cygwin-to-host-path,$1))
-else
-host-path = $1
-endif
-
-# -----------------------------------------------------------------------------
-# Function : host-rm
-# Arguments: 1: list of files
-# Usage    : $(call host-rm,<files>)
-# Rationale: This function expands to the host-specific shell command used
-#            to remove some files.
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),windows)
-host-rm = \
-    $(eval __host_rm_files := $(foreach __host_rm_file,$1,$(subst /,\,$(wildcard $(__host_rm_file)))))\
-    $(if $(__host_rm_files),del /f/q $(__host_rm_files) >NUL 2>NUL)
-else
-host-rm = rm -f $1
-endif
-
-# -----------------------------------------------------------------------------
-# Function : host-rmdir
-# Arguments: 1: list of files or directories
-# Usage    : $(call host-rm,<files>)
-# Rationale: This function expands to the host-specific shell command used
-#            to remove some files _and_ directories.
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),windows)
-host-rmdir = \
-    $(eval __host_rmdir_files := $(foreach __host_rmdir_file,$1,$(subst /,\,$(wildcard $(__host_rmdir_file)))))\
-    $(if $(__host_rmdir_files),del /f/s/q $(__host_rmdir_files) >NUL 2>NUL)
-else
-host-rmdir = rm -rf $1
-endif
-
-# -----------------------------------------------------------------------------
-# Function : host-mkdir
-# Arguments: 1: directory path
-# Usage    : $(call host-mkdir,<path>
-# Rationale: This function expands to the host-specific shell command used
-#            to create a path if it doesn't exist.
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),windows)
-host-mkdir = md $(subst /,\,"$1") >NUL 2>NUL || rem
-else
-host-mkdir = mkdir -p $1
-endif
-
-# -----------------------------------------------------------------------------
-# Function : host-cp
-# Arguments: 1: source file
-#            2: target file
-# Usage    : $(call host-cp,<src-file>,<dst-file>)
-# Rationale: This function expands to the host-specific shell command used
-#            to copy a single file
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),windows)
-host-cp = copy /b/y $(subst /,\,"$1" "$2") > NUL
-else
-host-cp = cp -f $1 $2
-endif
-
-# -----------------------------------------------------------------------------
-# Function : host-install
-# Arguments: 1: source file
-#            2: target file
-# Usage    : $(call host-install,<src-file>,<dst-file>)
-# Rationale: This function expands to the host-specific shell command used
-#            to install a file or directory, while preserving its timestamps
-#            (if possible).
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),windows)
-host-install = copy /b/y $(subst /,\,"$1" "$2") > NUL
-else
-host-install = install -p $1 $2
-endif
-
-# -----------------------------------------------------------------------------
-# Function : host-c-includes
-# Arguments: 1: list of file paths (e.g. "foo bar")
-# Returns  : list of include compiler options (e.g. "-Ifoo -Ibar")
-# Usage    : $(call host-c-includes,<paths>)
-# Rationale: This function is used to translate Cygwin paths into
-#            Cygwin-specific ones. On other platforms, it will just
-#            return its argument.
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),cygwin)
-host-c-includes = $(patsubst %,-I%,$(call host-path,$1))
-else
-host-c-includes = $(1:%=-I%)
-endif
-
-# -----------------------------------------------------------------------------
-# Function : copy-if-differ
-# Arguments: 1: source file
-#            2: destination file
-# Usage    : $(call copy-if-differ,<src-file>,<dst-file>)
-# Rationale: This function copy source file to destination file if contents are
-#            different.
-# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS),windows)
-copy-if-differ = $(HOST_CMP) -s $1 $2 > NUL || copy /b/y $(subst /,\,"$1" "$2") > NUL
-else
-copy-if-differ = $(HOST_CMP) -s $1 $2 > /dev/null 2>&1 || cp -f $1 $2
-endif
-
-# -----------------------------------------------------------------------------
 # Function : generate-dir
 # Arguments: 1: directory path
 # Returns  : Generate a rule, but not dependency, to create a directory with
@@ -320,9 +135,27 @@
 index-is-zero = $(filter 0 00 000 0000 00000 000000 0000000,$1)
 bump-0-to-1 = $(if $(call index-is-zero,$1),1,$1)
 
+-test-bump-0-to-1 = \
+  $(call test-expect,$(call bump-0-to-1))\
+  $(call test-expect,1,$(call bump-0-to-1,0))\
+  $(call test-expect,1,$(call bump-0-to-1,1))\
+  $(call test-expect,2,$(call bump-0-to-1,2))\
+  $(call test-expect,1,$(call bump-0-to-1,00))\
+  $(call test-expect,1,$(call bump-0-to-1,000))\
+  $(call test-expect,1,$(call bump-0-to-1,0000))\
+  $(call test-expect,1,$(call bump-0-to-1,00000))\
+  $(call test-expect,1,$(call bump-0-to-1,000000))\
+  $(call test-expect,10,$(call bump-0-to-1,10))\
+  $(call test-expect,100,$(call bump-0-to-1,100))
+
 # Same as $(wordlist ...) except the start index, if 0, is bumped to 1
 index-word-list = $(wordlist $(call bump-0-to-1,$1),$2,$3)
 
+-test-index-word-list = \
+  $(call test-expect,,$(call index-word-list,1,1))\
+  $(call test-expect,a b,$(call index-word-list,0,2,a b c d))\
+  $(call test-expect,b c,$(call index-word-list,2,3,a b c d))\
+
 # NOTE: With GNU Make $1 and $(1) are equivalent, which means
 #       that $10 is equivalent to $(1)0, and *not* $(10).
 
@@ -466,7 +299,7 @@
 $(call list-file-maybe-gen-1000,5,$1)
 
 $$(__list_file): $$(__list_file).tmp
-	$$(hide) $$(call copy-if-differ,$$@.tmp,$$@)
+	$$(hide) $$(call host-copy-if-differ,$$@.tmp,$$@)
 	$$(hide) $$(call host-rm,$$@.tmp)
 
 endef
@@ -487,6 +320,13 @@
 link-whole-archives = $(if $(strip $1),$(call link-whole-archive-flags,$1))
 link-whole-archive-flags = -Wl,--whole-archive $(call host-path,$1) -Wl,--no-whole-archive
 
+-test-link-whole-archive = \
+  $(call test-expect,,$(call link-whole-archives))\
+  $(eval _start := -Wl,--whole-archive)\
+  $(eval _end := -Wl,--no-whole-archive)\
+  $(call test-expect,$(_start) foo $(_end),$(call link-whole-archives,foo))\
+  $(call test-expect,$(_start) foo bar $(_end),$(call link-whole-archives,foo bar))
+
 # =============================================================================
 #
 # Modules database
@@ -641,6 +481,8 @@
   $(if $(call module-class-is-installable,$(LOCAL_MODULE_CLASS)),\
     $(eval LOCAL_INSTALLED := $(NDK_APP_DST_DIR)/$(notdir $(LOCAL_BUILT_MODULE)))\
   )\
+  $(foreach __field,STATIC_LIBRARIES WHOLE_STATIC_LIBRARIES SHARED_LIBRARIES,\
+    $(eval LOCAL_$(__field) := $(call strip-lib-prefix,$(LOCAL_$(__field)))))\
   $(foreach __local,$(modules-LOCALS),\
     $(eval __ndk_modules.$1.$(__local) := $(LOCAL_$(__local)))\
   )\
@@ -704,7 +546,7 @@
 
 # Dump all module information. Only use this for debugging
 modules-dump-database = \
-    $(info Modules: $(__ndk_modules)) \
+    $(info Modules [$(TARGET_ARCH_ABI)]: $(__ndk_modules)) \
     $(foreach __mod,$(__ndk_modules),\
         $(info $(space4)$(__mod):)\
         $(foreach __field,$(modules-fields),\
@@ -751,7 +593,146 @@
 # NOTE: this function must not modify the existing dependency order when new depends are added.
 #
 module-add-depends-any = \
-    $(eval __ndk_modules.$1.$3 += $(filter-out $(__ndk_modules.$1.$3),$(call strip-lib-prefix,$2)))
+    $(eval __ndk_modules.$1.$3 += $(filter-out $(__ndk_modules.$1.$3),$2))
+
+
+# -----------------------------------------------------------------------------
+# Returns non-empty if a module is a static library
+# Arguments: 1: module name
+# Returns     : non-empty iff the module is a static library.
+# Usage       : $(if $(call module-is-static-library,<name>),...)
+# -----------------------------------------------------------------------------
+module-is-static-library = $(strip \
+  $(filter STATIC_LIBRARY PREBUILT_STATIC_LIBRARY,\
+    $(call module-get-class,$1)))
+
+# -----------------------------------------------------------------------------
+# Returns non-empty if a module is a shared library
+# Arguments: 1: module name
+# Returns     : non-empty iff the module is a shared library.
+# Usage       : $(if $(call module-is-shared-library,<name>),...)
+# -----------------------------------------------------------------------------
+module-is-shared-library = $(strip \
+  $(filter SHARED_LIBRARY PREBUILT_SHARED_LIBRARY,\
+    $(call module-get-class,$1)))
+
+# -----------------------------------------------------------------------------
+# Filter a list of module names to retain only the static libraries.
+# Arguments: 1: module name list
+# Returns     : input list modules which are static libraries.
+# -----------------------------------------------------------------------------
+module-filter-static-libraries = $(call filter-by,$1,module-is-static-library)
+
+# -----------------------------------------------------------------------------
+# Filter a list of module names to retain only the shared libraries.
+# Arguments: 1: module name list
+# Returns     : input list modules which are shared libraries.
+# -----------------------------------------------------------------------------
+module-filter-shared-libraries = $(call filter-by,$1,module-is-shared-library)
+
+# -----------------------------------------------------------------------------
+# Return the LOCAL_STATIC_LIBRARIES for a given module.
+# Arguments: 1: module name
+# Returns     : List of static library modules.
+# -----------------------------------------------------------------------------
+module-get-static-libs = $(__ndk_modules.$1.STATIC_LIBRARIES)
+
+# -----------------------------------------------------------------------------
+# Return the LOCAL_WHOLE_STATIC_LIBRARIES for a given module.
+# Arguments: 1: module name
+# Returns     : List of whole static library modules.
+# -----------------------------------------------------------------------------
+module-get-whole-static-libs = $(__ndk_modules.$1.WHOLE_STATIC_LIBRARIES)
+
+# -----------------------------------------------------------------------------
+# Return all static libraries for a given module.
+# Arguments: 1: module name
+# Returns     : List of static library modules (whole or not).
+# -----------------------------------------------------------------------------
+module-get-all-static-libs = $(strip \
+  $(__ndk_modules.$1.STATIC_LIBRARIES) \
+  $(__ndk_modules.$1.WHOLE_STATIC_LIBRARIES))
+
+# -----------------------------------------------------------------------------
+# Return the list of LOCAL_SHARED_LIBRARIES for a given module.
+# Arguments: 1: module name
+# Returns     : List of shared library modules.
+# -----------------------------------------------------------------------------
+module-get-shared-libs = $(__ndk_modules.$1.SHARED_LIBRARIES)
+
+# -----------------------------------------------------------------------------
+# Return the list of all libraries a modules depends directly on.
+# This is the concatenation of its LOCAL_STATIC_LIBRARIES,
+# LOCAL_WHOLE_STATIC_LIBRARIES, and LOCAL_SHARED_LIBRARIES variables.
+# Arguments: 1: module name
+# Returns     : List of library modules (static or shared).
+# -----------------------------------------------------------------------------
+module-get-direct-libs = $(strip \
+  $(__ndk_modules.$1.STATIC_LIBRARIES) \
+  $(__ndk_modules.$1.WHOLE_STATIC_LIBRARIES) \
+  $(__ndk_modules.$1.SHARED_LIBRARIES))
+
+
+# -----------------------------------------------------------------------------
+# Computes the full closure of a module and its dependencies. Order is
+# defined by a breadth-first walk of the graph.
+# $1 will be the first item in the result.
+#
+# Arguments: 1: module name
+# Returns     : List of all modules $1 depends on.
+#
+# Note: Do not use this to determine build dependencies. The returned list
+#       is much too large for this. For example consider the following
+#       dependency graph:
+#
+#   main.exe -> libA.a -> libfoo.so -> libB.a
+#
+#       This function will return all four modules in the result, while
+#       at link time building main.exe only requires the first three.
+#
+# -----------------------------------------------------------------------------
+module-get-all-dependencies = $(call -ndk-mod-get-closure,$1,module-get-depends)
+
+# -----------------------------------------------------------------------------
+# Compute the list of all static and shared libraries required to link a
+# given module.
+#
+# Note that the result is topologically ordered, i.e. if library A depends
+# on library B, then A will always appear after B in the result.
+#
+# Arguments: 1: module name
+# Returns     : List of all library $1 depends at link time.
+#
+# Note: This doesn't differentiate between regular and whole static
+#       libraries. Use module-extract-whole-static-libs to filter the
+#       result returned by this function.
+# -----------------------------------------------------------------------------
+module-get-link-libs = $(strip \
+  $(eval _ndk_mod_link_module := $1) \
+  $(call -ndk-mod-get-topological-depends,$1,-ndk-mod-link-deps))
+
+# Special dependency function used by nodule-get-link-libs.
+# The rules to follow are the following:
+#  - if $1 is the link module, or if it is a static library, then all
+#    direct dependencies.
+#  - otherwise, the module is a shared library, don't add build deps.
+-ndk-mod-link-deps = \
+  $(if $(call seq,$1,$(_ndk_mod_link_module))$(call module-is-static-library,$1),\
+    $(call module-get-direct-libs,$1))
+
+# -----------------------------------------------------------------------------
+# This function is used to extract the list of static libraries that need
+# to be linked as whole, i.e. placed in a special section on the final
+# link command.
+# Arguments: $1: module name.
+#            $2: list of all static link-time libraries (regular or whole).
+# Returns  : list of static libraries from '$2' that need to be linked
+#            as whole.
+# -----------------------------------------------------------------------------
+module-extract-whole-static-libs = $(strip \
+  $(eval _ndk_mod_whole_all := $(call map,module-get-whole-static-libs,$1 $2))\
+  $(eval _ndk_mod_whole_result := $(filter $(_ndk_mod_whole_all),$2))\
+  $(_ndk_mod_whole_result))
 
 # Used to recompute all dependencies once all module information has been recorded.
 #
@@ -767,47 +748,7 @@
 
 module-get-installed = $(__ndk_modules.$1.INSTALLED)
 
-# -----------------------------------------------------------------------------
-# Function : modules-get-all-dependencies
-# Arguments: 1: list of module names
-# Returns  : List of all the modules $1 depends on transitively.
-# Usage    : $(call modules-all-get-dependencies,<list of module names>)
-# Rationale: This computes the closure of all module dependencies starting from $1
-# -----------------------------------------------------------------------------
-module-get-all-dependencies = $(strip \
-    $(call modules-get-closure,$1,depends))
-
-modules-get-closure = \
-    $(eval __closure_deps  := $(strip $(call strip-lib-prefix,$1))) \
-    $(eval __closure_wq    := $(__closure_deps)) \
-    $(eval __closure_field := $(strip $2)) \
-    $(call modules-closure)\
-    $(__closure_deps)
-
-# Used internally by modules-get-all-dependencies
-# Note the tricky use of conditional recursion to work around the fact that
-# the GNU Make language does not have any conditional looping construct
-# like 'while'.
-#
-modules-closure = \
-    $(eval __closure_mod := $(call first,$(__closure_wq))) \
-    $(eval __closure_wq  := $(call rest,$(__closure_wq))) \
-    $(eval __closure_val := $(call strip-lib-prefix,$(__ndk_modules.$(__closure_mod).$(__closure_field)))) \
-    $(eval __closure_new := $(filter-out $(__closure_deps),$(__closure_val)))\
-    $(eval __closure_deps += $(__closure_new)) \
-    $(eval __closure_wq   := $(strip $(__closure_wq) $(__closure_new)))\
-    $(if $(__closure_wq),$(call modules-closure)) \
-
-# -----------------------------------------------------------------------------
-# Function : module-get-depends
-# Arguments: 1: list of module names
-#            2: local module type (e.g. SHARED_LIBRARIES)
-# Returns  : List all the <local-type> modules $1 depends on transitively.
-# Usage    : $(call module-get-depends,<list of module names>,<local-type>)
-# Rationale: This computes the closure of all local module dependencies starting from $1
-# -----------------------------------------------------------------------------
-module-get-depends = $(strip $(call modules-get-closure,$1,$2))
-
+module-get-depends = $(__ndk_modules.$1.depends)
 
 # -----------------------------------------------------------------------------
 # Function : modules-get-all-installable
@@ -818,7 +759,7 @@
 # -----------------------------------------------------------------------------
 # For now, only the closure of LOCAL_SHARED_LIBRARIES is enough
 modules-get-all-installable = $(strip \
-    $(foreach __alldep,$(call module-get-depends,$1,depends),\
+    $(foreach __alldep,$(call module-get-all-dependencies,$1),\
         $(if $(call module-is-installable,$(__alldep)),$(__alldep))\
     ))
 
@@ -945,14 +886,6 @@
 # =============================================================================
 
 # -----------------------------------------------------------------------------
-# Function : parent-dir
-# Arguments: 1: path
-# Returns  : Parent dir or path of $1, with final separator removed.
-# -----------------------------------------------------------------------------
-parent-dir = $(patsubst %/,%,$(dir $1))
-
-
-# -----------------------------------------------------------------------------
 # Function : pretty-dir
 # Arguments: 1: path
 # Returns  : Remove NDK_PROJECT_PATH prefix from a given path. This can be
@@ -961,6 +894,15 @@
 pretty-dir = $(patsubst $(NDK_ROOT)/%,<NDK>/%,\
                  $(patsubst $(NDK_PROJECT_PATH)/%,%,$1))
 
+# Note: NDK_PROJECT_PATH is typically defined after this test is run.
+-test-pretty-dir = \
+  $(eval NDK_PROJECT_PATH ?= .)\
+  $(call test-expect,foo,$(call pretty-dir,foo))\
+  $(call test-expect,foo,$(call pretty-dir,$(NDK_PROJECT_PATH)/foo))\
+  $(call test-expect,foo/bar,$(call pretty-dir,$(NDK_PROJECT_PATH)/foo/bar))\
+  $(call test-expect,<NDK>/foo,$(call pretty-dir,$(NDK_ROOT)/foo))\
+  $(call test-expect,<NDK>/foo/bar,$(call pretty-dir,$(NDK_ROOT)/foo/bar))
+
 # -----------------------------------------------------------------------------
 # Function : check-user-define
 # Arguments: 1: name of variable that must be defined by the user
@@ -1002,7 +944,7 @@
         $(call __ndk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_MODULE_FILENAME must not contain spaces)\
         $(call __ndk_error,Plase correct error. Aborting)\
     )\
-    $(if $(filter %.a %.so,$(LOCAL_MODULE_FILENAME)),\
+    $(if $(filter %$(TARGET_LIB_EXTENSION) %$(TARGET_SONAME_EXTENSION),$(LOCAL_MODULE_FILENAME)),\
         $(call __ndk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_MODULE_FILENAME should not include file extensions)\
     )\
   )
@@ -1029,7 +971,7 @@
     $$(call __ndk_info,$$(LOCAL_MAKEFILE):$$(LOCAL_MODULE): LOCAL_MODULE_FILENAME must not contain any space)
     $$(call __ndk_error,Aborting)
 endif
-ifneq (,$$(filter %.a %.so,$$(LOCAL_MODULE_FILENAME)))
+ifneq (,$$(filter %$$(TARGET_LIB_EXTENSION) %$$(TARGET_SONAME_EXTENSION),$$(LOCAL_MODULE_FILENAME)))
     $$(call __ndk_info,$$(LOCAL_MAKEFILE):$$(LOCAL_MODULE): LOCAL_MODULE_FILENAME must not contain a file extension)
     $$(call __ndk_error,Aborting)
 endif
@@ -1067,8 +1009,8 @@
 LOCAL_MODULE_FILENAME := $$(strip $$(LOCAL_MODULE_FILENAME))
 ifndef LOCAL_MODULE_FILENAME
     LOCAL_MODULE_FILENAME := $$(notdir $(LOCAL_SRC_FILES))
-    LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME:%.a=%)
-    LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME:%.so=%)
+    LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME:%$$(TARGET_LIB_EXTENSION)=%)
+    LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME:%$$(TARGET_SONAME_EXTENSION)=%)
 endif
 LOCAL_MODULE_FILENAME := $$(LOCAL_MODULE_FILENAME)$1
 $$(eval $$(call ev-check-module-filename))
@@ -1087,16 +1029,6 @@
     $(eval LOCAL_OBJS_DIR     := $(TARGET_OBJS)/$(LOCAL_MODULE))
 
 # -----------------------------------------------------------------------------
-# Strip any 'lib' prefix in front of a given string.
-#
-# Function : strip-lib-prefix
-# Arguments: 1: module name
-# Returns  : module name, without any 'lib' prefix if any
-# Usage    : $(call strip-lib-prefix,$(LOCAL_MODULE))
-# -----------------------------------------------------------------------------
-strip-lib-prefix = $(1:lib%=%)
-
-# -----------------------------------------------------------------------------
 # Compute the real path of a prebuilt file.
 #
 # Function : local-prebuilt-path
@@ -1333,11 +1265,19 @@
     $(subst ../,__/,\
         $(eval __obj := $1)\
         $(foreach __ext,.c .s .S $(LOCAL_CPP_EXTENSION),\
-            $(eval __obj := $(__obj:%$(__ext)=%.o))\
+            $(eval __obj := $(__obj:%$(__ext)=%$(TARGET_OBJ_EXTENSION)))\
         )\
         $(__obj)\
     ))
 
+-test-get-object-name = \
+  $(eval TARGET_OBJ_EXTENSION=.o)\
+  $(eval LOCAL_CPP_EXTENSION ?= .cpp)\
+  $(call test-expect,foo.o,$(call get-object-name,foo.c))\
+  $(call test-expect,bar.o,$(call get-object-name,bar.s))\
+  $(call test-expect,zoo.o,$(call get-object-name,zoo.S))\
+  $(call test-expect,tot.o,$(call get-object-name,tot.cpp))
+
 # -----------------------------------------------------------------------------
 # Macro    : hide
 # Returns  : nothing
@@ -1445,8 +1385,8 @@
   _ORG_FLAGS := $$(_FLAGS)
   _ORG_TEXT  := $$(_TEXT)
 
-  _OBJ_ASM_ORIGINAL := $$(patsubst %.o,%.s,$$(_ORG_OBJ))
-  _OBJ_ASM_FILTERED := $$(patsubst %.o,%.filtered.s,$$(_ORG_OBJ))
+  _OBJ_ASM_ORIGINAL := $$(patsubst %$$(TARGET_OBJ_EXTENSION),%.s,$$(_ORG_OBJ))
+  _OBJ_ASM_FILTERED := $$(patsubst %$$(TARGET_OBJ_EXTENSION),%.filtered.s,$$(_ORG_OBJ))
 
   # If the source file is a plain assembler file, we're going to
   # use it directly in our filter.
@@ -1723,12 +1663,12 @@
 
 # static libraries:
 # <foo> -> lib<foo>.a by default
-$(call module-class-register,STATIC_LIBRARY,lib,.a)
+$(call module-class-register,STATIC_LIBRARY,lib,$(TARGET_LIB_EXTENSION))
 
 # shared libraries:
 # <foo> -> lib<foo>.so
 # a shared library is installable.
-$(call module-class-register-installable,SHARED_LIBRARY,lib,.so)
+$(call module-class-register-installable,SHARED_LIBRARY,lib,$(TARGET_SONAME_EXTENSION))
 
 # executable
 # <foo> -> <foo>
@@ -1762,8 +1702,8 @@
     $(eval __ndk_stl := $(strip $1)) \
     $(eval NDK_STL_LIST += $(__ndk_stl)) \
     $(eval NDK_STL.$(__ndk_stl).IMPORT_MODULE := $(strip $2)) \
-    $(eval NDK_STL.$(__ndk_stl).STATIC_LIBS := $(strip $3)) \
-    $(eval NDK_STL.$(__ndk_stl).SHARED_LIBS := $(strip $4))
+    $(eval NDK_STL.$(__ndk_stl).STATIC_LIBS := $(strip $(call strip-lib-prefix,$3))) \
+    $(eval NDK_STL.$(__ndk_stl).SHARED_LIBS := $(strip $(call strip-lib-prefix,$4)))
 
 # Called to check that the value of APP_STL is a valid one.
 # $1: STL name as it apperas in APP_STL (e.g. 'system')
@@ -1857,3 +1797,7 @@
     none,\
     cxx-stl/system,\
     )
+
+ifneq (,$(NDK_UNIT_TESTS))
+$(call ndk-run-all-tests)
+endif
diff --git a/build/core/prebuilt-library.mk b/build/core/prebuilt-library.mk
index 91e8f3c..4c7d93d 100644
--- a/build/core/prebuilt-library.mk
+++ b/build/core/prebuilt-library.mk
@@ -47,7 +47,7 @@
 
 # If LOCAL_MODULE_FILENAME is defined, it will be used to name the file
 # in the TARGET_OUT directory, and then the installation one. Note that
-# if shouldn't have an .a or .so extension nor contain directory separators.
+# it shouldn't have an .a or .so extension nor contain directory separators.
 #
 # If the variable is not defined, we determine its value from LOCAL_SRC_FILES
 #
diff --git a/build/core/prebuilt-shared-library.mk b/build/core/prebuilt-shared-library.mk
index afe5e4b..77ccb11 100644
--- a/build/core/prebuilt-shared-library.mk
+++ b/build/core/prebuilt-shared-library.mk
@@ -22,6 +22,6 @@
 LOCAL_MAKEFILE     := $(local-makefile)
 
 LOCAL_PREBUILT_PREFIX := lib
-LOCAL_PREBUILT_SUFFIX := .so
+LOCAL_PREBUILT_SUFFIX := $(TARGET_SONAME_EXTENSION)
 
 include $(BUILD_SYSTEM)/prebuilt-library.mk
diff --git a/build/core/prebuilt-static-library.mk b/build/core/prebuilt-static-library.mk
index 26087c3..07d981b 100644
--- a/build/core/prebuilt-static-library.mk
+++ b/build/core/prebuilt-static-library.mk
@@ -22,7 +22,7 @@
 LOCAL_MAKEFILE     := $(local-makefile)
 
 LOCAL_PREBUILT_PREFIX := lib
-LOCAL_PREBUILT_SUFFIX := .a
+LOCAL_PREBUILT_SUFFIX := $(TARGET_LIB_EXTENSION)
 
 # Prebuilt static libraries don't need to be copied to TARGET_OUT
 # to facilitate debugging, so use the prebuilt version directly
diff --git a/build/core/setup-app.mk b/build/core/setup-app.mk
index c972bbc..1e27dc3 100644
--- a/build/core/setup-app.mk
+++ b/build/core/setup-app.mk
@@ -72,7 +72,7 @@
 ifeq ($(NDK_APP.$(_app).cleaned_binaries),)
     NDK_APP.$(_app).cleaned_binaries := true
     clean-installed-binaries::
-	$(hide) $(call host-rm,$(NDK_ALL_ABIS:%=$(NDK_APP_PROJECT_PATH)/libs/%/lib*.so))
+	$(hide) $(call host-rm,$(NDK_ALL_ABIS:%=$(NDK_APP_PROJECT_PATH)/libs/%/lib*$(TARGET_SONAME_EXTENSION)))
 	$(hide) $(call host-rm,$(NDK_ALL_ABIS:%=$(NDK_APP_PROJECT_PATH)/libs/%/gdbserver))
 	$(hide) $(call host-rm,$(NDK_ALL_ABIS:%=$(NDK_APP_PROJECT_PATH)/libs/%/gdb.setup))
 endif
diff --git a/build/core/setup-toolchain.mk b/build/core/setup-toolchain.mk
index 978c4c8..6397772 100644
--- a/build/core/setup-toolchain.mk
+++ b/build/core/setup-toolchain.mk
@@ -66,6 +66,10 @@
         # TARGET_TOOLCHAIN_BASE will be 'foo-bar-zoo'
         #
         TARGET_TOOLCHAIN_BASE := $(subst $(space),-,$(call chop,$(subst -,$(space),$(TARGET_TOOLCHAIN))))
+        # if TARGET_TOOLCHAIN_BASE is llvm, remove clang from NDK_TOOLCHAIN_VERSION
+        ifeq ($(TARGET_TOOLCHAIN_BASE),llvm)
+            NDK_TOOLCHAIN_VERSION := $(subst clang,,$(NDK_TOOLCHAIN_VERSION))
+        endif
         TARGET_TOOLCHAIN := $(TARGET_TOOLCHAIN_BASE)-$(NDK_TOOLCHAIN_VERSION)
         $(call ndk_log,Using target toolchain '$(TARGET_TOOLCHAIN)' for '$(TARGET_ARCH_ABI)' ABI (through NDK_TOOLCHAIN_VERSION))
     else
@@ -144,6 +148,7 @@
 NDK_APP_GDBSETUP := $(NDK_APP_DST_DIR)/gdb.setup
 
 ifeq ($(NDK_APP_DEBUGGABLE),true)
+ifeq ($(TARGET_SONAME_EXTENSION),.so)
 
 installed_modules: $(NDK_APP_GDBSERVER)
 
@@ -173,6 +178,7 @@
 # This prevents parallel execution to clear gdb.setup after it has been written to
 $(NDK_APP_GDBSETUP): clean-installed-binaries
 endif
+endif
 
 # free the dictionary of LOCAL_MODULE definitions
 $(call modules-clear)
diff --git a/build/tools/build-analyzer.sh b/build/tools/build-analyzer.sh
index d56c3d9..05e9871 100755
--- a/build/tools/build-analyzer.sh
+++ b/build/tools/build-analyzer.sh
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-#  This shell script is used to copy clang tool "scan-build"
+#  This shell script is used to copy clang tool "scan-build" and "scan-view"
 #  for the Android NDK.
 #
 
@@ -56,6 +56,12 @@
         exit 1
     fi
 
+    SCAN_VIEW_SRC_DIR=$SRC_DIR/$TOOLCHAIN/clang/tools/scan-view
+    if [ ! -d "$SCAN_VIEW_SRC_DIR" ] ; then
+        echo "ERROR: Source directory does not contain scan-view: $SCAN_VIEW_SRC_DIR"
+        exit 1
+    fi
+
     LICENSE_FILE=$SRC_DIR/$TOOLCHAIN/clang/LICENSE.TXT
     if [ ! -f "$LICENSE_FILE" ] ; then
         echo "ERROR: Source directory does not contain clang license file: $LICENSE_FILE"
@@ -93,18 +99,20 @@
     fail_panic "Could not create package directory: $PACKAGE_DIR"
 fi
 
-# copy scan_build
+# copy scan_build and scan_view
 SCAN_BUILD_SUBDIR="prebuilt/common/scan-build"
 run copy_directory "$SCAN_BUILD_SRC_DIR" "$NDK_DIR/$SCAN_BUILD_SUBDIR"
 cp -p "$LICENSE_FILE" "$NDK_DIR/$SCAN_BUILD_SUBDIR"
-
-# remove unneeded file(s)
 rm -f $NDK_DIR/$SCAN_BUILD_SUBDIR/scan-build.1
 
+SCAN_VIEW_SUBDIR="prebuilt/common/scan-view"
+run copy_directory "$SCAN_VIEW_SRC_DIR" "$NDK_DIR/$SCAN_VIEW_SUBDIR"
+cp -p "$LICENSE_FILE" "$NDK_DIR/$SCAN_VIEW_SUBDIR"
+
 if [ "$PACKAGE_DIR" ]; then
-    ARCHIVE="scan-build.tar.bz2"
+    ARCHIVE="scan-build-view.tar.bz2"
     dump "Packaging $ARCHIVE"
-    pack_archive "$PACKAGE_DIR/$ARCHIVE" "$NDK_DIR" "$SCAN_BUILD_SUBDIR"
+    pack_archive "$PACKAGE_DIR/$ARCHIVE" "$NDK_DIR" "$SCAN_BUILD_SUBDIR" "$SCAN_VIEW_SUBDIR"
 fi
 
 dump "Done."
diff --git a/build/tools/build-gcc.sh b/build/tools/build-gcc.sh
index 331c585..5cd3411 100755
--- a/build/tools/build-gcc.sh
+++ b/build/tools/build-gcc.sh
@@ -251,7 +251,7 @@
     # this is compiler requirement to have binutils configured this way. Flag
     # --disable-plugin is for gcc.
     case "$GCC_VERSION" in
-        4.4.3|4.6)
+        4.4.3)
             EXTRA_CONFIG_FLAGS=$EXTRA_CONFIG_FLAGS" --disable-plugin"
             ;;
         *)
diff --git a/build/tools/build-gnu-libstdc++.sh b/build/tools/build-gnu-libstdc++.sh
index f42240e..927cb86 100755
--- a/build/tools/build-gnu-libstdc++.sh
+++ b/build/tools/build-gnu-libstdc++.sh
@@ -64,6 +64,9 @@
 NO_MAKEFILE=
 register_var_option "--no-makefile" NO_MAKEFILE "Do not use makefile to speed-up build"
 
+VISIBLE_LIBGNUSTL_STATIC=
+register_var_option "--visible-libgnustl-static" VISIBLE_LIBGNUSTL_STATIC "Do not use hidden visibility for libgnustl_static.a"
+
 register_jobs_option
 
 extract_parameters "$@"
@@ -184,13 +187,15 @@
     if [ $LIBTYPE = "static" ]; then
         # Ensure we disable visibility for the static library to reduce the
         # size of the code that will be linked against it.
-        LIBTYPE_FLAGS="--enable-static --disable-shared"
-        if [ $GCC_VERSION = "4.4.3" -o $GCC_VERSION = "4.6" ]; then
-            LIBTYPE_FLAGS=$LIBTYPE_FLAGS" --disable-visibility"
-        else
-            LIBTYPE_FLAGS=$LIBTYPE_FLAGS" --disable-libstdcxx-visibility"
+        if [ -z "$VISIBLE_LIBGNUSTL_STATIC" ] ; then
+            LIBTYPE_FLAGS="--enable-static --disable-shared"
+            if [ $GCC_VERSION = "4.4.3" -o $GCC_VERSION = "4.6" ]; then
+                LIBTYPE_FLAGS=$LIBTYPE_FLAGS" --disable-visibility"
+            else
+                LIBTYPE_FLAGS=$LIBTYPE_FLAGS" --disable-libstdcxx-visibility"
+            fi
+            CXXFLAGS=$CXXFLAGS" -fvisibility=hidden -fvisibility-inlines-hidden"
         fi
-        CXXFLAGS=$CXXFLAGS" -fvisibility=hidden -fvisibility-inlines-hidden"
     else
         LIBTYPE_FLAGS="--disable-static --enable-shared"
         #LDFLAGS=$LDFLAGS" -lsupc++"
diff --git a/build/tools/build-host-gcc.sh b/build/tools/build-host-gcc.sh
index 2145396..c91fa71 100755
--- a/build/tools/build-host-gcc.sh
+++ b/build/tools/build-host-gcc.sh
@@ -127,6 +127,9 @@
 NDK_DIR=$ANDROID_NDK_ROOT
 register_var_option "--ndk-dir=<path>" NDK_DIR "Select NDK install directory"
 
+BUILD_DIR=
+register_var_option "--build-dir=<path>" BUILD_DIR "Build GCC into directory"
+
 PACKAGE_DIR=
 register_var_option "--package-dir=<path>" PACKAGE_DIR "Package prebuilt tarballs into directory"
 
@@ -174,6 +177,10 @@
     panic "Please use --toolchain-src-dir=<path> to select toolchain source directory."
 fi
 
+if [ -z "$BUILD_DIR" ]; then
+    BUILD_DIR=/tmp/ndk-$USER/build/host-gcc
+fi
+
 case $DEFAULT_LD in
     gold|bfd)
       ;;
@@ -451,7 +458,6 @@
 
 setup_build ()
 {
-    BUILD_DIR=/tmp/ndk-$USER/build/host-gcc
     run_on_setup mkdir -p "$BUILD_DIR"
     if [ -n "$FORCE" ]; then
         rm -rf "$BUILD_DIR"/*
@@ -489,17 +495,6 @@
     fi
 }
 
-get_default_binutils_version_for_gcc ()
-{
-    local RET
-    case $1 in
-        arm-*-4.4.3|x86-*-4.4.3|x86-4.4.3) RET=2.19;;
-        *-4.6) RET=2.21;;
-        *) RET=2.22;;
-    esac
-    echo "$RET"
-}
-
 # Check that a given compiler generates code correctly
 #
 # This is to detect bad/broken toolchains, e.g. amd64-mingw32msvc
@@ -1262,16 +1257,11 @@
 
     LD_NAME=$DEFAULT_LD
 
-    # Enable Gold, for specific builds. The version before binutils 2.21
-    # is buggy so don't use it
-    case $HOST_OS in
-        windows) BUILD_GOLD=;; # Gold doesn't compile on Windows!
-        darwin) BUILD_GOLD=;;  # Building Gold fails with an internal compiler error on Darwin!
-        *) BUILD_GOLD=true;;
-    esac
+    # Enable Gold globally. It can be built for all hosts.
+    BUILD_GOLD=true
 
-    # Special case, gold in binutil-2.21 doesn't build when targetting mips
-    if [ "$BINUTILS_VERSION" = "2.21" -a "$TARGET" = "mipsel-linux-android" ]; then
+    # Special case, gold is not ready for mips yet.
+    if [ "$TARGET" = "mipsel-linux-android" ]; then
         BUILD_GOLD=
     fi
 
@@ -1280,6 +1270,12 @@
     #
     if [ "$BINUTILS_VERSION" = "2.21" -a "$TARGET" = "i686-linux-android" ]; then
         USE_LD_DEFAULT=true
+        BUILD_GOLD=
+    fi
+
+    # Another special case. Not or 2.19, it wasn't ready
+    if [ "$BINUTILS_VERSION" = "2.19" ]; then
+        BUILD_GOLD=
     fi
 
     if [ "$DEFAULT_LD" = "gold" -a -z "$BUILD_GOLD" ]; then
@@ -1299,6 +1295,7 @@
     # The BFD linker is always built, but to build Gold, we need a specific
     # option for the binutils configure script. Note that its format has
     # changed during development.
+    export host_configargs=
     if [ "$BUILD_GOLD" ]; then
         # The syntax of the --enable-gold option has changed.
         if version_is_greater_than $BINUTILS_VERSION 2.20; then
@@ -1314,11 +1311,19 @@
                 ARGS=$ARGS" --enable-gold=both/gold"
             fi
         fi
+	# This ARG needs quoting when passed to run2.
+	GOLD_LDFLAGS_ARG=
         if [ "$HOST_OS" = 'windows' ]; then
             # gold may have runtime dependency on libgcc_sjlj_1.dll and
             # libstdc++-6.dll when built by newer versions of mingw.
             # Link them statically to avoid that.
-            ARGS=$ARGS" --with-gold-ldflags='-static-libgcc -static-libstdc++'"
+            if version_is_greater_than $BINUTILS_VERSION 2.22; then
+                export host_configargs="--with-gold-ldflags='-static-libgcc -static-libstdc++'"
+            elif version_is_greater_than $BINUTILS_VERSION 2.21; then
+                GOLD_LDFLAGS_ARG="--with-gold-ldflags=-static-libgcc -static-libstdc++"
+            else
+                export LDFLAGS=$LDFLAGS" -static-libgcc -static-libstdc++"
+            fi
         fi
     fi
 
@@ -1329,7 +1334,7 @@
     # like build-host-libbfd.sh in the future.
     ARGS=$ARGS" --enable-install-libbfd"
 
-    # Enable plugins support for binutils-2.21+
+    # Enable plugins support for > binutils-2.19
     # This is common feature for binutils and gcc
     case "$BINUTILS_VERSION" in
       2.19)
@@ -1400,15 +1405,24 @@
 
     ARGS=$HOST_PREREQS_ARGS
 
+    # Plugins are not supported well before 4.7. On 4.7 it's required to have
+    # -flto working. Flag --enable-plugins (note 's') is actually for binutils,
+    # this is compiler requirement to have binutils configured this way. Flag
+    # --disable-plugin is for gcc -
+    # In fact, enable-plugins is broken all Canadian Cross GCC.
+    #  see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50229
     case "$GCC_VERSION" in
-      4.4.3|4.6)
-        ARGS=$ARGS" --disable-plugin"
-        ;;
+     4.4.3|4.6|4.7)
+       ARGS=$ARGS" --disable-plugins --disable-plugin"
+       ;;
+    # Doesn't even work on 4.8
+     *)
+       ARGS=$ARGS" --enable-plugins  --enable-plugin"
+       ;;
     esac
 
     ARGS=$ARGS" --with-gnu-as --with-gnu-ld"
     ARGS=$ARGS" --enable-threads --disable-libssp --disable-libmudflap"
-    ARGS=$ARGS" --disable-libgomp"  # TODO: Add option to enable this
     ARGS=$ARGS" --disable-libstdc__-v3 --disable-sjlj-exceptions"
     ARGS=$ARGS" --disable-tls"
     ARGS=$ARGS" --disable-libquadmath --disable-libitm --disable-bootstrap"
@@ -1418,6 +1432,19 @@
     ARGS=$ARGS" --disable-werror"
     ARGS=$ARGS" --enable-target-optspace"
 
+    case "$GCC_VERSION" in
+     4.4.3)
+       ARGS=$ARGS" --disable-libgomp"
+       ;;
+     *)
+       case $TARGET_ARCH in
+	     arm) ARGS=$ARGS" --enable-libgomp";;
+	     x86) ARGS=$ARGS" --disable-libgomp";;
+	     mips|mipsel) ARGS=$ARGS" --disable-libgomp";;
+	 esac
+	 ;;
+    esac
+
     # Place constructors/destructors in .init_array/.fini_array, not in
     # .ctors/.dtors on Android. Note that upstream Linux GLibc is now doing
     # the same.
diff --git a/build/tools/build-host-gdb.sh b/build/tools/build-host-gdb.sh
index 4727439..2c3f91c 100755
--- a/build/tools/build-host-gdb.sh
+++ b/build/tools/build-host-gdb.sh
@@ -144,7 +144,7 @@
     local ARGS
     local SRCDIR=$TOOLCHAIN_SRC_DIR/expat/expat-2.0.1
     local BUILDDIR=$BH_BUILD_DIR/build-expat-2.0.1-$1
-    local INSTALLDIR=$BH_BUILD_DIR/install-expat-2.0.1-$1
+    local INSTALLDIR=$BH_BUILD_DIR/install-host-$1
 
     ARGS=" --prefix=$INSTALLDIR"
     ARGS=$ARGS" --disable-shared --enable-static"
@@ -184,7 +184,7 @@
     bh_setup_host_env
 
     need_build_expat $1
-    local EXPATPREFIX=$BH_BUILD_DIR/install-expat-2.0.1-$1
+    local EXPATPREFIX=$BH_BUILD_DIR/install-host-$1
 
     ARGS=" --prefix=$INSTALLDIR"
     ARGS=$ARGS" --disable-shared"
@@ -194,7 +194,8 @@
     ARGS=$ARGS" --disable-werror"
     ARGS=$ARGS" --disable-nls"
     ARGS=$ARGS" --disable-docs"
-    ARGS=$ARGS" --with-expat=$EXPATPREFIX"
+    ARGS=$ARGS" --with-expat"
+    ARGS=$ARGS" --with-libexpat-prefix=$EXPATPREFIX"
     if [ "$PYTHON_VERSION" ]; then
         ARGS=$ARGS" --with-python=$(python_build_install_dir $BH_HOST_TAG)/bin/python-config.sh"
         if [ $1 = windows-x86 -o $1 = windows-x86_64 ]; then
@@ -203,7 +204,6 @@
             CXXFLAGS=$CXXFLAGS" -D__USE_MINGW_ANSI_STDIO=1"
         fi
     fi
-
     TEXT="$(bh_host_text) gdb-$BH_TARGET_ARCH-$3:"
 
     mkdir -p "$BUILDDIR" && rm -rf "$BUILDDIR"/* &&
@@ -280,7 +280,7 @@
         bh_setup_build_for_host $SYSTEM
         for ARCH in $ARCHS; do
             for VERSION in $GDB_VERSION; do
-                package_host_gdb $SYSTEM android-$ARCH $VERSION
+                bh_stamps_do package_host_gdb-$SYSTEM-$ARCH-$VERSION package_host_gdb $SYSTEM android-$ARCH $VERSION
             done
         done
     done
diff --git a/build/tools/build-llvm.sh b/build/tools/build-llvm.sh
index 4157d77..f4daf9e 100755
--- a/build/tools/build-llvm.sh
+++ b/build/tools/build-llvm.sh
@@ -238,11 +238,11 @@
     --with-bug-report-url=$DEFAULT_ISSUE_TRACKER_URL \
     --enable-targets=arm,mips,x86 \
     --enable-optimized \
+    --with-binutils-include=$SRC_DIR/binutils/binutils-$DEFAULT_BINUTILS_VERSION/include \
     $EXTRA_CONFIG_FLAGS
 fail_panic "Couldn't configure llvm toolchain"
 
-
-# build the toolchain
+# build llvm/clang
 dump "Building : llvm toolchain [this can take a long time]."
 cd $LLVM_BUILD_OUT
 run make -j$NUM_JOBS $MAKE_FLAGS
@@ -263,22 +263,68 @@
 fi
 
 # install the toolchain to its final location
-dump "Install  : llvm toolchain binaries."
+dump "Install  : llvm toolchain binaries"
 cd $LLVM_BUILD_OUT && run make install $MAKE_FLAGS
 fail_panic "Couldn't install llvm toolchain to $TOOLCHAIN_BUILD_PREFIX"
 
-# clean static or shared libraries
+# Build mclinker only against default the LLVM version, once
+# mclinker isn't mingw-ready yet.  ToDo
+if [ "$TOOLCHAIN" = "llvm-$DEFAULT_LLVM_VERSION" -a "$MINGW" != "yes" ] ; then
+    dump "Copy     : mclinker source"
+    MCLINKER_SRC_DIR=$BUILD_OUT/mclinker
+    mkdir -p $MCLINKER_SRC_DIR
+    fail_panic "Couldn't create mclinker source directory: $MCLINKER_SRC_DIR"
+
+    run copy_directory "$SRC_DIR/mclinker" "$MCLINKER_SRC_DIR"
+    fail_panic "Couldn't copy mclinker source: $MCLINKER_SRC_DIR"
+
+    cd $MCLINKER_SRC_DIR && run ./autogen.sh
+    fail_panic "Couldn't run autogen.sh in $MCLINKER_SRC_DIR"
+
+    dump "Configure: mclinker against $TOOLCHAIN"
+    MCLINKER_BUILD_OUT=$MCLINKER_SRC_DIR/build
+    mkdir -p $MCLINKER_BUILD_OUT && cd $MCLINKER_BUILD_OUT
+    fail_panic "Couldn't cd into mclinker build path: $MCLINKER_BUILD_OUT"
+
+    run $MCLINKER_SRC_DIR/configure \
+        --prefix=$TOOLCHAIN_BUILD_PREFIX \
+        --with-llvm-config=$TOOLCHAIN_BUILD_PREFIX/bin/llvm-config \
+        --host=$ABI_CONFIGURE_HOST \
+        --build=$ABI_CONFIGURE_BUILD \
+        --with-bug-report-url=$DEFAULT_ISSUE_TRACKER_URL
+    fail_panic "Couldn't configure mclinker"
+
+    dump "Building : mclinker"
+    cd $MCLINKER_BUILD_OUT
+    run make -j$NUM_JOBS $MAKE_FLAGS
+    fail_panic "Couldn't compile mclinker"
+
+    dump "Install  : mclinker"
+    cd $MCLINKER_BUILD_OUT && run make install $MAKE_FLAGS
+    fail_panic "Couldn't install mclinker to $TOOLCHAIN_BUILD_PREFIX"
+
+    if [ "$CHECK" = "yes" -a "$MINGW" != "yes" -a "$DARWIN" != "yes" ] ; then
+        # run the regression test
+        dump "Running  : mclinker regression test"
+        cd $MCLINKER_BUILD_OUT
+        run make check
+        fail_warning "Couldn't pass all mclinker regression test"  # change to fail_panic later
+    fi
+fi
+
+# remove redundant bits
 rm -rf $TOOLCHAIN_BUILD_PREFIX/docs
 rm -rf $TOOLCHAIN_BUILD_PREFIX/include
 rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/*.a
 rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/*.la
 rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/pkgconfig
-rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/lib*.so
-rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/lib*.dylib
+rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/lib[cp]*.so
+rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/lib[cp]*.dylib
 rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/B*.so
 rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/B*.dylib
 rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/LLVMH*.so
 rm -rf $TOOLCHAIN_BUILD_PREFIX/lib/LLVMH*.dylib
+rm -rf $TOOLCHAIN_BUILD_PREFIX/bin/ld.bcc*
 rm -rf $TOOLCHAIN_BUILD_PREFIX/share
 
 UNUSED_LLVM_EXECUTABLES="
diff --git a/build/tools/build-target-prebuilts.sh b/build/tools/build-target-prebuilts.sh
index 725c5c8..4d17e3d 100755
--- a/build/tools/build-target-prebuilts.sh
+++ b/build/tools/build-target-prebuilts.sh
@@ -29,6 +29,9 @@
 PACKAGE_DIR=
 register_var_option "--package-dir=<path>" PACKAGE_DIR "Package toolchain into this directory"
 
+VISIBLE_LIBGNUSTL_STATIC=
+register_var_option "--visible-libgnustl-static" VISIBLE_LIBGNUSTL_STATIC "Do not use hidden visibility for libgnustl_static.a"
+
 register_jobs_option
 
 PROGRAM_PARAMETERS="<toolchain-src-dir>"
@@ -93,6 +96,10 @@
 run $BUILDTOOLS/build-stlport.sh $FLAGS
 fail_panic "Could not build stlport!"
 
+if [ ! -z $VISIBLE_LIBGNUSTL_STATIC ]; then
+    FLAGS=$FLAGS" --visible-libgnustl-static"
+fi
+
 dump "Building $ABIS gnustl binaries..."
 run $BUILDTOOLS/build-gnu-libstdc++.sh $FLAGS "$SRC_DIR"
 fail_panic "Could not build gnustl!"
diff --git a/build/tools/download-toolchain-sources.sh b/build/tools/download-toolchain-sources.sh
index c1cdd70..bb739a4 100755
--- a/build/tools/download-toolchain-sources.sh
+++ b/build/tools/download-toolchain-sources.sh
@@ -201,6 +201,7 @@
 toolchain_clone python
 toolchain_clone clang
 toolchain_clone llvm
+toolchain_clone mclinker
 
 toolchain_checkout "" $BRANCH build .
 toolchain_checkout "" $BRANCH gmp .
@@ -213,6 +214,7 @@
 toolchain_checkout "" $BRANCH gcc gcc-4.4.3 gcc-4.6 gcc-4.7
 toolchain_checkout "" $BRANCH gdb gdb-6.6 gdb-7.3.x
 toolchain_checkout "" $BRANCH python Python-2.7.3
+toolchain_checkout "" $BRANCH mclinker .
 
 for LLVM_VERSION in $LLVM_VERSION_LIST; do
     LLVM_VERSION_NO_DOT=$(echo $LLVM_VERSION | sed -e 's!\.!!g')
diff --git a/build/tools/gen-platforms.sh b/build/tools/gen-platforms.sh
index 0ced51f..3252fc7 100755
--- a/build/tools/gen-platforms.sh
+++ b/build/tools/gen-platforms.sh
@@ -68,6 +68,7 @@
 OPTION_ARCH=
 OPTION_ABI=
 OPTION_DEBUG_LIBS=
+OPTION_OVERLAY=
 PACKAGE_DIR=
 
 VERBOSE=no
@@ -118,6 +119,9 @@
   --debug-libs)
     OPTION_DEBUG_LIBS=true
     ;;
+  --overlay)
+    OPTION_OVERLAY=true
+    ;;
   *)
     echo "unknown option '$opt', use --help"
     exit 1
@@ -565,7 +569,9 @@
 #   $SRC/android-$PLATFORM/arch-$ARCH/include --> $DST/android-$PLATFORM/arch-$ARCH/usr/include
 #   $SRC/android-$PLATFORM/arch-$ARCH/lib --> $DST/android-$PLATFORM/arch-$ARCH/usr/lib
 #
-rm -rf $DSTDIR/platforms && mkdir -p $DSTDIR/platforms
+if [ -z "$OPTION_OVERLAY" ]; then
+    rm -rf $DSTDIR/platforms && mkdir -p $DSTDIR/platforms
+fi
 for ARCH in $ARCHS; do
     # Find first platform for this arch
     PREV_SYSROOT_DST=
@@ -651,7 +657,9 @@
     # $SRC/android-$PLATFORM/samples/ --> $DST/samples
     #
     dump "Copying generic samples"
-    rm -rf $DSTDIR/samples && mkdir -p $DSTDIR/samples
+    if [ -z "$OPTION_OVERLAY" ]; then
+        rm -rf $DSTDIR/samples && mkdir -p $DSTDIR/samples
+    fi
     copy_src_directory  samples samples samples
 
     for PLATFORM in $PLATFORMS; do
diff --git a/build/tools/package-release.sh b/build/tools/package-release.sh
index b6f518b..332d70e 100755
--- a/build/tools/package-release.sh
+++ b/build/tools/package-release.sh
@@ -82,9 +82,18 @@
 LLVM_VERSION_LIST=$DEFAULT_LLVM_VERSION_LIST
 register_var_option "--llvm=<versions>" LLVM_VERSION_LIST "List of LLVM release versions"
 
+register_try64_option
+
 SEPARATE_64=no
 register_option "--separate-64" do_SEPARATE_64 "Separate 64-bit host toolchain to its own package"
-do_SEPARATE_64 () { SEPARATE_64=yes; }
+do_SEPARATE_64 ()
+{
+    if [ "$TRY64" = "yes" ]; then
+        echo "ERROR: You cannot use both --try-64 and --separate-64 at the same time."
+        exit 1
+    fi
+    SEPARATE_64=yes;
+}
 
 PROGRAM_PARAMETERS=
 PROGRAM_DESCRIPTION=\
@@ -252,24 +261,49 @@
 # ensure that the generated files are ug+rx
 umask 0022
 
+# Translate name to 64-bit's counterpart
+# $1: prebuilt name
+name64 ()
+{
+    local NAME=$1
+    case $NAME in
+        *windows)
+            NAME=${NAME}-x86_64
+            ;;
+        *linux-x86|*darwin-x86)
+            NAME=${NAME}_64
+            ;;
+    esac
+    echo $NAME
+}
+
 # Unpack a prebuilt into specified destination directory
 # $1: prebuilt name, relative to $PREBUILT_DIR
 # $2: destination directory
 # $3: optional destination directory for 64-bit toolchain
+# $4: optional flag to use 32-bit prebuilt in place of 64-bit
 unpack_prebuilt ()
 {
-    local PREBUILT=${1}.tar.bz2
-    local PREBUILT64=${1}_64.tar.bz2
-    local PREBUILT64_ALT=${1}-x86_64.tar.bz2
+    local PREBUILT=
+    local PREBUILT64=null
     local DDIR="$2"
     local DDIR64="${3:-$DDIR}"
+    local USE32="${4:-no}"
+
+    if [ "$TRY64" = "yes" -a "$USE32" = "no" ]; then
+        PREBUILT=`name64 $1`
+    else
+        PREBUILT=$1
+        PREBUILT64=`name64 $1`
+    fi
+
+    PREBUILT=${PREBUILT}.tar.bz2
+    PREBUILT64=${PREBUILT64}.tar.bz2
+
     echo "Unpacking $PREBUILT"
     if [ -f "$PREBUILT_DIR/$PREBUILT" ] ; then
         unpack_archive "$PREBUILT_DIR/$PREBUILT" "$DDIR"
         fail_panic "Could not unpack prebuilt $PREBUILT. Aborting."
-        if [ ! -f "$PREBUILT_DIR/$PREBUILT64" ] ; then
-            PREBUILT64=$PREBUILT64_ALT
-        fi
         if [ -f "$PREBUILT_DIR/$PREBUILT64" ] ; then
             echo "Unpacking $PREBUILT64"
             unpack_archive "$PREBUILT_DIR/$PREBUILT64" "$DDIR64"
@@ -380,7 +414,11 @@
 # invoking the NDK from a release package or from the development
 # tree.
 #
-echo "$RELEASE" > $REFERENCE/RELEASE.TXT
+if [ "$TRY64" = "yes" ]; then
+    echo "$RELEASE (64-bit)" > $REFERENCE/RELEASE.TXT
+else
+    echo "$RELEASE" > $REFERENCE/RELEASE.TXT
+fi
 
 # Remove un-needed files
 rm -f $REFERENCE/CleanSpec.mk
@@ -445,10 +483,11 @@
         done
 
         # Unpack prebuilt ndk-stack and other host tools
-        unpack_prebuilt ndk-stack-$SYSTEM "$DSTDIR" "$DSTDIR64"
+        unpack_prebuilt ndk-stack-$SYSTEM "$DSTDIR" "$DSTDIR64" "yes"
         unpack_prebuilt ndk-make-$SYSTEM "$DSTDIR" "$DSTDIR64"
         unpack_prebuilt ndk-sed-$SYSTEM "$DSTDIR" "$DSTDIR64"
         unpack_prebuilt ndk-awk-$SYSTEM "$DSTDIR" "$DSTDIR64"
+        unpack_prebuilt ndk-perl-$SYSTEM "$DSTDIR" "$DSTDIR64"
 
         if [ "$SYSTEM" = "windows" ]; then
             unpack_prebuilt toolbox-$SYSTEM "$DSTDIR" "$DSTDIR64"
@@ -456,18 +495,22 @@
     fi
 
     # Unpack other host tools
-    unpack_prebuilt scan-build "$DSTDIR" "$DSTDIR64"
+    unpack_prebuilt scan-build-view "$DSTDIR" "$DSTDIR64"
 
     # Create an archive for the final package. Extension depends on the
     # host system.
+    ARCHIVE=$BIN_RELEASE
+    if [ "$TRY64" = "yes" ]; then
+        ARCHIVE=`name64 $ARCHIVE`
+    fi
     case "$SYSTEM" in
         windows)
-            ARCHIVE="$BIN_RELEASE.zip"
-            ARCHIVE64="$BIN_RELEASE-64bit-tools.zip"
+            ARCHIVE64="$ARCHIVE-64bit-tools.zip"
+            ARCHIVE="$ARCHIVE.zip"
             ;;
         *)
-            ARCHIVE="$BIN_RELEASE.tar.bz2"
-            ARCHIVE64="$BIN_RELEASE-64bit-tools.tar.bz2"
+            ARCHIVE64="$ARCHIVE-64bit-tools.tar.bz2"
+            ARCHIVE="$ARCHIVE.tar.bz2"
             ;;
     esac
     echo "Creating $ARCHIVE"
diff --git a/build/tools/toolchain-patches/mclinker/0001-Add-GCC-collect2-compatibility-flags.patch b/build/tools/toolchain-patches/mclinker/0001-Add-GCC-collect2-compatibility-flags.patch
new file mode 100644
index 0000000..ed3f915
--- /dev/null
+++ b/build/tools/toolchain-patches/mclinker/0001-Add-GCC-collect2-compatibility-flags.patch
@@ -0,0 +1,46 @@
+From bd187102557cfff78b1fe929db3466a3c775ebde Mon Sep 17 00:00:00 2001
+From: Andrew Hsieh <andrewhsieh@google.com>
+Date: Fri, 22 Feb 2013 12:30:18 +0800
+Subject: [PATCH 1/2] Add GCC/collect2 compatibility flags
+
+Add -use-gold, -use-mcld, and use-ld passed by GCC/collect2
+both ld.bfd ld.gold ignore
+
+Change-Id: Iaa1cb032c773d99bdc26ebf7335965c76e03a22d
+---
+ tools/llvm-mcld/llvm-mcld.cpp |   19 +++++++++++++++++++
+ 1 files changed, 19 insertions(+), 0 deletions(-)
+
+diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
+index 088ba07..e478729 100644
+--- a/tools/llvm-mcld/llvm-mcld.cpp
++++ b/tools/llvm-mcld/llvm-mcld.cpp
+@@ -792,6 +792,25 @@ ArgTextSegAddr("Ttext",
+                cl::init(-1U));
+ 
+ //===----------------------------------------------------------------------===//
++// Ignored GCC Compatibility Options
++//===----------------------------------------------------------------------===//
++static cl::opt<bool>
++ArgLDgold("use-gold",
++          cl::desc("GCC/collect2 compatibility: uses ld.gold.  Ignored"),
++          cl::init(false));
++
++static cl::opt<bool>
++ArgLDmcld("use-mcld",
++          cl::desc("GCC/collect2 compatibility: uses ld.mcld.  Ignored"),
++          cl::init(false));
++
++static cl::opt<bool>
++ArgLDbfd("use-ld",
++          cl::desc("GCC/collect2 compatibility: uses ld.bfd.  Ignored"),
++          cl::init(false));
++
++
++//===----------------------------------------------------------------------===//
+ // non-member functions
+ //===----------------------------------------------------------------------===//
+ /// GetOutputStream - get the output stream.
+-- 
+1.7.7.3
+
diff --git a/build/tools/toolchain-patches/mclinker/0002-Compile-agsint-llvm-3.2.patch b/build/tools/toolchain-patches/mclinker/0002-Compile-agsint-llvm-3.2.patch
new file mode 100644
index 0000000..3a41d64
--- /dev/null
+++ b/build/tools/toolchain-patches/mclinker/0002-Compile-agsint-llvm-3.2.patch
@@ -0,0 +1,92 @@
+From fb2eb10813621ec22963258220abd41e592fc430 Mon Sep 17 00:00:00 2001
+From: Andrew Hsieh <andrewhsieh@google.com>
+Date: Fri, 22 Feb 2013 12:33:36 +0800
+Subject: [PATCH 2/2] Compile agsint llvm 3.2
+
+Current mclinker needs LLVM -r 173175 which contains re-org of
+some headers from since LLVM 3.2.  This patch is to roll back
+so we can build from LLVM 3.2
+
+Change-Id: I634b7b0fa085e5bdb7a0a2861c47d6063bf36d25
+---
+ lib/CodeGen/MCLDTargetMachine.cpp |    2 +-
+ lib/CodeGen/MCLinker.cpp          |    2 +-
+ lib/Target/X86/X86Emulation.cpp   |    3 +--
+ lib/Target/X86/X86LDBackend.cpp   |    3 +--
+ tools/llvm-mcld/llvm-mcld.cpp     |    6 +++---
+ 5 files changed, 7 insertions(+), 9 deletions(-)
+
+diff --git a/lib/CodeGen/MCLDTargetMachine.cpp b/lib/CodeGen/MCLDTargetMachine.cpp
+index 785ef1f..8f5d998 100644
+--- a/lib/CodeGen/MCLDTargetMachine.cpp
++++ b/lib/CodeGen/MCLDTargetMachine.cpp
+@@ -26,7 +26,7 @@
+ #include <llvm/CodeGen/MachineModuleInfo.h>
+ #include <llvm/CodeGen/GCStrategy.h>
+ #include <llvm/CodeGen/Passes.h>
+-#include <llvm/IR/DataLayout.h>
++#include <llvm/DataLayout.h>
+ #include <llvm/MC/MCAsmInfo.h>
+ #include <llvm/MC/MCStreamer.h>
+ #include <llvm/MC/MCInstrInfo.h>
+diff --git a/lib/CodeGen/MCLinker.cpp b/lib/CodeGen/MCLinker.cpp
+index 3613a03..909278f 100644
+--- a/lib/CodeGen/MCLinker.cpp
++++ b/lib/CodeGen/MCLinker.cpp
+@@ -28,7 +28,7 @@
+ #include <mcld/Support/raw_ostream.h>
+ #include <mcld/Support/MemoryArea.h>
+ 
+-#include <llvm/IR/Module.h>
++#include <llvm/Module.h>
+ #include <llvm/Support/CommandLine.h>
+ 
+ #include <algorithm>
+diff --git a/lib/Target/X86/X86Emulation.cpp b/lib/Target/X86/X86Emulation.cpp
+index 753d7cc..1e17b03 100644
+--- a/lib/Target/X86/X86Emulation.cpp
++++ b/lib/Target/X86/X86Emulation.cpp
+@@ -23,8 +23,7 @@ static bool MCLDEmulateX86ELF(LinkerConfig& pConfig)
+   unsigned int bitclass;
+   Triple::ArchType arch = pConfig.targets().triple().getArch();
+   assert (arch == Triple::x86 || arch == Triple::x86_64);
+-  if (arch == Triple::x86 ||
+-      pConfig.targets().triple().getEnvironment() == Triple::GNUX32) {
++  if (arch == Triple::x86) {
+     bitclass = 32;
+   }
+   else {
+diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
+index 85c80a7..2203499 100644
+--- a/lib/Target/X86/X86LDBackend.cpp
++++ b/lib/Target/X86/X86LDBackend.cpp
+@@ -46,8 +46,7 @@ X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig,
+ {
+   Triple::ArchType arch = pConfig.targets().triple().getArch();
+   assert (arch == Triple::x86 || arch == Triple::x86_64);
+-  if (arch == Triple::x86 ||
+-      pConfig.targets().triple().getEnvironment() == Triple::GNUX32) {
++  if (arch == Triple::x86) {
+     m_RelEntrySize = 8;
+     m_RelaEntrySize = 12;
+     if (arch == Triple::x86)
+diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
+index e478729..1f77ed1 100644
+--- a/tools/llvm-mcld/llvm-mcld.cpp
++++ b/tools/llvm-mcld/llvm-mcld.cpp
+@@ -24,9 +24,9 @@
+ 
+ #include <llvm/PassManager.h>
+ #include <llvm/Pass.h>
+-#include <llvm/IR/Module.h>
+-#include <llvm/IR/DataLayout.h>
+-#include <llvm/IR/LLVMContext.h>
++#include <llvm/Module.h>
++#include <llvm/DataLayout.h>
++#include <llvm/LLVMContext.h>
+ #include <llvm/ADT/Triple.h>
+ #include <llvm/MC/SubtargetFeature.h>
+ #include <llvm/Support/CommandLine.h>
+-- 
+1.7.7.3
+
diff --git a/docs/ANDROID-MK.html b/docs/ANDROID-MK.html
index e431694..accc01f 100644
--- a/docs/ANDROID-MK.html
+++ b/docs/ANDROID-MK.html
@@ -548,6 +548,13 @@
     See docs/STABLE-APIS.html for the list of exposed system libraries you
     can linked against with this NDK release.
 
+LOCAL_LDFLAGS
+    The list of other linker flags to be used when building your module.
+    For example, the following will use linker ld.bfd on ARM/X86 GCC 4.6/4.7
+    where ld.gold is the default
+
+      LOCAL_LDFLAGS += -fuse-ld=bfd
+
 LOCAL_ALLOW_UNDEFINED_SYMBOLS
     By default, any undefined reference encountered when trying to build
     a shared library will result in an "undefined symbol" error. This is a
diff --git a/docs/STANDALONE-TOOLCHAIN.html b/docs/STANDALONE-TOOLCHAIN.html
index 3763a16..c7a428e 100644
--- a/docs/STANDALONE-TOOLCHAIN.html
+++ b/docs/STANDALONE-TOOLCHAIN.html
@@ -96,7 +96,7 @@
 
 You may specify --system=linux-x86_64 on 64-bit Linux or --system=darwin-x86_64 on 64-bit
 MacOSX to make 64-bit host toolchain instead of the 32-bit one (default).
-64-bit Windows toolchain isn't available yet.  See IV of NDK-BUILD.html
+See IV of NDK-BUILD.html
 
 You can later use it directly with something like:
 
diff --git a/sources/android/cpufeatures/cpu-features.c b/sources/android/cpufeatures/cpu-features.c
index 5b0a9d9..119c2ac 100644
--- a/sources/android/cpufeatures/cpu-features.c
+++ b/sources/android/cpufeatures/cpu-features.c
@@ -123,22 +123,22 @@
 
     fd = open(pathname, O_RDONLY);
     if (fd < 0) {
-      D("Can't open %s: %s\n", pathname, strerror(errno));
-      return -1;
+        D("Can't open %s: %s\n", pathname, strerror(errno));
+        return -1;
     }
 
     for (;;) {
-      int ret = read(fd, buffer, sizeof buffer);
-      if (ret < 0) {
-        if (errno == EINTR)
-          continue;
-        D("Error while reading %s: %s\n", pathname, strerror(errno));
-        break;
-      }
-      if (ret == 0)
-        break;
+        int ret = read(fd, buffer, sizeof buffer);
+        if (ret < 0) {
+            if (errno == EINTR)
+                continue;
+            D("Error while reading %s: %s\n", pathname, strerror(errno));
+            break;
+        }
+        if (ret == 0)
+            break;
 
-      result += ret;
+        result += ret;
     }
     close(fd);
     return result;
@@ -185,10 +185,10 @@
  * Return NULL if not found
  */
 static char*
-extract_cpuinfo_field(char* buffer, int buflen, const char* field)
+extract_cpuinfo_field(const char* buffer, int buflen, const char* field)
 {
     int  fieldlen = strlen(field);
-    char* bufend = buffer + buflen;
+    const char* bufend = buffer + buflen;
     char* result = NULL;
     int len, ignore;
     const char *p, *q;
@@ -421,11 +421,22 @@
 
 #define AT_HWCAP 16
 
-/* Read the ELF HWCAP flags by parsing /proc/self/auxv
+#if defined(__arm__)
+/* Compute the ELF HWCAP flags.
  */
 static uint32_t
-get_elf_hwcap(void)
+get_elf_hwcap(const char* cpuinfo, int cpuinfo_len)
 {
+  /* IMPORTANT:
+   *   Accessing /proc/self/auxv doesn't work anymore on all
+   *   platform versions. More specifically, when running inside
+   *   a regular application process, most of /proc/self/ will be
+   *   non-readable, including /proc/self/auxv. This doesn't
+   *   happen however if the application is debuggable, or when
+   *   running under the "shell" UID, which is why this was not
+   *   detected appropriately.
+   */
+#if 0
     uint32_t result = 0;
     const char filepath[] = "/proc/self/auxv";
     int fd = open(filepath, O_RDONLY);
@@ -454,7 +465,40 @@
     }
     close(fd);
     return result;
+#else
+    // Recreate ELF hwcaps by parsing /proc/cpuinfo Features tag.
+    uint32_t hwcaps = 0;
+
+    char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
+
+    if (cpuFeatures != NULL) {
+        D("Found cpuFeatures = '%s'\n", cpuFeatures);
+
+        if (has_list_item(cpuFeatures, "vfp"))
+            hwcaps |= HWCAP_VFP;
+        if (has_list_item(cpuFeatures, "vfpv3"))
+            hwcaps |= HWCAP_VFPv3;
+        if (has_list_item(cpuFeatures, "vfpv3d16"))
+            hwcaps |= HWCAP_VFPv3D16;
+        if (has_list_item(cpuFeatures, "vfpv4"))
+            hwcaps |= HWCAP_VFPv4;
+        if (has_list_item(cpuFeatures, "neon"))
+            hwcaps |= HWCAP_NEON;
+        if (has_list_item(cpuFeatures, "idiva"))
+            hwcaps |= HWCAP_IDIVA;
+        if (has_list_item(cpuFeatures, "idivt"))
+            hwcaps |= HWCAP_IDIVT;
+        if (has_list_item(cpuFeatures, "idiv"))
+            hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT;
+        if (has_list_item(cpuFeatures, "iwmmxt"))
+            hwcaps |= HWCAP_IWMMXT;
+
+        free(cpuFeatures);
+    }
+    return hwcaps;
+#endif
 }
+#endif  /* __arm__ */
 
 /* Return the number of cpus present on a given device.
  *
@@ -601,7 +645,7 @@
         }
 
         /* Extract the list of CPU features from ELF hwcaps */
-        uint32_t hwcaps = get_elf_hwcap();
+        uint32_t hwcaps = get_elf_hwcap(cpuinfo, cpuinfo_len);
 
         if (hwcaps != 0) {
             int has_vfp = (hwcaps & HWCAP_VFP);
@@ -618,9 +662,9 @@
 
             // 'vfpv4' implies VFPv3|VFP_FMA|FP16
             if (has_vfpv4)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3    |
-                               ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
-                               ANDROID_CPU_ARM_FEATURE_VFP_FMA;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3    |
+                                 ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
+                                 ANDROID_CPU_ARM_FEATURE_VFP_FMA;
 
             // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC,
             // a value of 'vfpv3' doesn't necessarily mean that the D32
@@ -628,42 +672,42 @@
             // field that support D32 also support NEON, so this should
             // not be a problem in practice.
             if (has_vfpv3 || has_vfpv3d16)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
 
             // 'vfp' is super ambiguous. Depending on the kernel, it can
             // either mean VFPv2 or VFPv3. Make it depend on ARMv7.
             if (has_vfp) {
               if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7)
-                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
               else
-                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
+                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
             }
 
             // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA
             if (has_neon) {
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
-                               ANDROID_CPU_ARM_FEATURE_NEON |
-                               ANDROID_CPU_ARM_FEATURE_VFP_D32;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
+                                 ANDROID_CPU_ARM_FEATURE_NEON |
+                                 ANDROID_CPU_ARM_FEATURE_VFP_D32;
               if (has_vfpv4)
-                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
+                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
             }
 
             // VFPv3 implies VFPv2 and ARMv7
             if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
-                               ANDROID_CPU_ARM_FEATURE_ARMv7;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
+                                 ANDROID_CPU_ARM_FEATURE_ARMv7;
 
             // Note that some buggy kernels do not report these even when
             // the CPU actually support the division instructions. However,
             // assume that if 'vfpv4' is detected, then the CPU supports
             // sdiv/udiv properly.
             if (has_idiva || has_vfpv4)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
             if (has_idivt || has_vfpv4)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
 
             if (has_iwmmxt)
-              g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
+                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
         }
     }
 #endif /* __ARM_ARCH__ */
diff --git a/sources/cxx-stl/gabi++/include/cstdlib b/sources/cxx-stl/gabi++/include/cstdlib
index bb6f5a5..ef29fa7 100644
--- a/sources/cxx-stl/gabi++/include/cstdlib
+++ b/sources/cxx-stl/gabi++/include/cstdlib
@@ -50,7 +50,6 @@
 using ::putenv;
 using ::setenv;
 using ::unsetenv;
-using ::clearenv;
 
 using ::mktemp;
 using ::mkstemp;
@@ -112,6 +111,11 @@
 using ::mbtowc;
 using ::wctomb;
 using ::wcstombs;
+
+#if __ANDROID_API__ >= 9
+using ::clearenv;
+#endif
+
 }  // namespace std
 
 }  // extern C++
diff --git a/sources/cxx-stl/gabi++/include/cxxabi.h b/sources/cxx-stl/gabi++/include/cxxabi.h
index a064c70..c6a4f8a 100644
--- a/sources/cxx-stl/gabi++/include/cxxabi.h
+++ b/sources/cxx-stl/gabi++/include/cxxabi.h
@@ -265,7 +265,7 @@
   extern "C" {
 
     // Compatible with GNU C++
-    const uint64_t __gxx_exception_class = 0x474E5543432B2B00; // GNUCC++\0
+    const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0
 
     // TODO: Support dependent exception
     // TODO: Support C++0x exception propagation
diff --git a/sources/cxx-stl/gabi++/include/stl_pair.h b/sources/cxx-stl/gabi++/include/stl_pair.h
index 37f757b..648f213 100644
--- a/sources/cxx-stl/gabi++/include/stl_pair.h
+++ b/sources/cxx-stl/gabi++/include/stl_pair.h
@@ -58,6 +58,14 @@
 #ifndef __SGI_STL_INTERNAL_PAIR_H
 #define __SGI_STL_INTERNAL_PAIR_H
 
+#ifndef __STL_BEGIN_NAMESPACE
+#define __STL_BEGIN_NAMESPACE namespace std {
+#endif
+
+#ifndef __STL_END_NAMESPACE
+#define __STL_END_NAMESPACE   }
+#endif
+
 __STL_BEGIN_NAMESPACE
 
 template <class _T1, class _T2>
diff --git a/sources/cxx-stl/system/include/cstdlib b/sources/cxx-stl/system/include/cstdlib
index bb6f5a5..ef29fa7 100644
--- a/sources/cxx-stl/system/include/cstdlib
+++ b/sources/cxx-stl/system/include/cstdlib
@@ -50,7 +50,6 @@
 using ::putenv;
 using ::setenv;
 using ::unsetenv;
-using ::clearenv;
 
 using ::mktemp;
 using ::mkstemp;
@@ -112,6 +111,11 @@
 using ::mbtowc;
 using ::wctomb;
 using ::wcstombs;
+
+#if __ANDROID_API__ >= 9
+using ::clearenv;
+#endif
+
 }  // namespace std
 
 }  // extern C++
diff --git a/sources/cxx-stl/system/include/stl_pair.h b/sources/cxx-stl/system/include/stl_pair.h
index 37f757b..648f213 100644
--- a/sources/cxx-stl/system/include/stl_pair.h
+++ b/sources/cxx-stl/system/include/stl_pair.h
@@ -58,6 +58,14 @@
 #ifndef __SGI_STL_INTERNAL_PAIR_H
 #define __SGI_STL_INTERNAL_PAIR_H
 
+#ifndef __STL_BEGIN_NAMESPACE
+#define __STL_BEGIN_NAMESPACE namespace std {
+#endif
+
+#ifndef __STL_END_NAMESPACE
+#define __STL_END_NAMESPACE   }
+#endif
+
 __STL_BEGIN_NAMESPACE
 
 template <class _T1, class _T2>
diff --git a/tests/build/ndk-build-unit-tests/build.sh b/tests/build/ndk-build-unit-tests/build.sh
new file mode 100755
index 0000000..a1f0bb9
--- /dev/null
+++ b/tests/build/ndk-build-unit-tests/build.sh
@@ -0,0 +1,5 @@
+# This is used to check that the internal unit tests of ndk-build
+# work properly. Note that these only check internal Make functions
+# within the build system, not anything that tries to build something.
+cd $(dirname "$0")
+$NDK/ndk-build NDK_UNIT_TESTS=1 clean
diff --git a/tests/build/topological-sort/BROKEN_BUILD b/tests/build/ndk-build-unit-tests/jni/Android.mk
similarity index 100%
rename from tests/build/topological-sort/BROKEN_BUILD
rename to tests/build/ndk-build-unit-tests/jni/Android.mk
diff --git a/tests/build/system-cpp-headers/jni/Android.mk b/tests/build/system-cpp-headers/jni/Android.mk
new file mode 100644
index 0000000..1f1f659
--- /dev/null
+++ b/tests/build/system-cpp-headers/jni/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_system_cpp_headers
+LOCAL_SRC_FILES := main.cpp
+LOCAL_C_INCLUDES := $(NDK_ROOT)/sources/cxx-stl/system/include
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_gabixx_cpp_headers
+LOCAL_SRC_FILES := main.cpp
+LOCAL_STATIC_LIBRARIES := libgabi++_static
+include $(BUILD_EXECUTABLE)
+
+include $(NDK_ROOT)/sources/cxx-stl/gabi++/Android.mk
diff --git a/tests/build/system-cpp-headers/jni/Application.mk b/tests/build/system-cpp-headers/jni/Application.mk
new file mode 100644
index 0000000..7a8e91a
--- /dev/null
+++ b/tests/build/system-cpp-headers/jni/Application.mk
@@ -0,0 +1,2 @@
+APP_STL := none
+APP_PLATFORM := android-3
diff --git a/tests/build/system-cpp-headers/jni/main.cpp b/tests/build/system-cpp-headers/jni/main.cpp
new file mode 100644
index 0000000..81b71cd
--- /dev/null
+++ b/tests/build/system-cpp-headers/jni/main.cpp
@@ -0,0 +1,25 @@
+// Check that including <cstdlib> doesn't result in a build error
+// with API level 3.
+#include <cassert>
+#include <cctype>
+#include <cerrno>
+#include <climits>
+#include <cmath>
+#include <csetjmp>
+#include <csignal>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <cwchar>
+#include <new>
+#include <new>
+#include <stl_pair.h>
+#include <typeinfo>
+#include <utility>
+
+int main(void) {
+  return 0;
+}
diff --git a/tests/build/topological-sort/jni/main.c b/tests/build/topological-sort/jni/main.c
index dcc85dc..3f20987 100644
--- a/tests/build/topological-sort/jni/main.c
+++ b/tests/build/topological-sort/jni/main.c
@@ -1,3 +1,5 @@
+#include <stdio.h>
+
 #include "foo.h"
 #include "bar.h"
 
diff --git a/tests/device/emm/jni/Android.mk b/tests/device/emm/jni/Android.mk
new file mode 100644
index 0000000..aa7b0b6
--- /dev/null
+++ b/tests/device/emm/jni/Android.mk
@@ -0,0 +1,7 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := emm
+LOCAL_SRC_FILES := emm.c
+include $(BUILD_EXECUTABLE)
+
diff --git a/tests/device/emm/jni/Application.mk b/tests/device/emm/jni/Application.mk
new file mode 100644
index 0000000..5eaff6d
--- /dev/null
+++ b/tests/device/emm/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := x86
diff --git a/tests/device/emm/jni/emm.c b/tests/device/emm/jni/emm.c
new file mode 100644
index 0000000..5cf1e3b
--- /dev/null
+++ b/tests/device/emm/jni/emm.c
@@ -0,0 +1,15 @@
+#include <emmintrin.h>
+
+int main()
+{
+    __m64 *p;
+    __m128 *q;
+    int p_isaligned, q_isaligned;
+    p = _mm_malloc(7*sizeof(*p),sizeof(*p));
+    q = _mm_malloc(5*sizeof(*q),sizeof(*q));
+    p_isaligned = ((int)p % sizeof(*p)) == 0;
+    q_isaligned = ((int)q % sizeof(*q)) == 0;
+    free(p);
+    free(q);
+    return (p_isaligned && q_isaligned)? 0 : 1;
+}
diff --git a/tests/device/test-stlport/BROKEN_RUN b/tests/device/test-stlport/BROKEN_RUN
deleted file mode 100644
index 17d604b..0000000
--- a/tests/device/test-stlport/BROKEN_RUN
+++ /dev/null
@@ -1 +0,0 @@
-clang3.1 clang3.2
\ No newline at end of file
diff --git a/tests/run-tests-all.sh b/tests/run-tests-all.sh
index 9cea1e2..73d90ef 100755
--- a/tests/run-tests-all.sh
+++ b/tests/run-tests-all.sh
@@ -49,17 +49,26 @@
 case "$HOST_TAG" in
     linux-x86_64|darwin-x86_64)
         if [ -d "$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/$HOST_TAG" ] ; then
-            # ideally we should check each individual compiler the presence of 64-bit
-            # but for test script this is fine
-            TEST_HOST_32BIT=yes
-            TAGS=$TAGS" $HOST_TAG32"
+            if [ -d "$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/$HOST_TAG32" ] ; then
+                # ideally we should check each individual compiler the presence of 64-bit
+                # but for test script this is fine
+                TEST_HOST_32BIT=yes
+                TAGS=$TAGS" $HOST_TAG32"
+            fi
+        else
+            TAGS=$HOST_TAG32
         fi
     ;;
     windows*)
-        if [ "$ProgramW6432"!="" -a \
-             -d "$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64" ] ; then
-            TEST_HOST_32BIT=yes
-            TAGS=$TAGS" windows-x86_64"
+        if [ "$ProgramW6432"!="" -a ] ; then
+            if [ -d "$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64" ] ; then
+                if [ -d "$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/windows" ] ; then
+                    TEST_HOST_32BIT=yes
+                    TAGS=$TAGS" windows-x86_64"
+                fi
+            else
+                TAGS=windows
+            fi
         fi
 esac
 
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index 31f4d15..8a5d3e6 100755
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -473,7 +473,7 @@
                 # only skip listed in file
                 TARGET_TOOLCHAIN=`get_build_var $PROJECT TARGET_TOOLCHAIN`
                 TARGET_TOOLCHAIN_VERSION=`echo $TARGET_TOOLCHAIN | tr '-' '\n' | tail -1`
-                grep -q -w -e "$TARGET_TOOLCHAIN_VERSION" "$PROJECT/BROKEN_BUILD"
+                grep -q -e "$TARGET_TOOLCHAIN_VERSION" "$PROJECT/BROKEN_BUILD"
                 if [ $? = 0 ] ; then
                     if [ -z "$ERRMSG" ] ; then
                         echo "Skipping `basename $PROJECT`: (no build for $TARGET_TOOLCHAIN_VERSION)"
@@ -685,7 +685,7 @@
                     # skip all tests built by toolchain
                     TARGET_TOOLCHAIN=`get_build_var $TEST TARGET_TOOLCHAIN`
                     TARGET_TOOLCHAIN_VERSION=`echo $TARGET_TOOLCHAIN | tr '-' '\n' | tail -1`
-                    grep -q -w -e "$TARGET_TOOLCHAIN_VERSION" "$TEST/BROKEN_RUN"
+                    grep -q -e "$TARGET_TOOLCHAIN_VERSION" "$TEST/BROKEN_RUN"
                     if [ $? = 0 ] ; then
                         dump "Skipping NDK device test run: $TEST_NAME (no run for binary built by $TARGET_TOOLCHAIN_VERSION)"
                         return 0