Separate cc.go

Split cc.go into files per module type, plus files for the compiler,
linker, and installer stages.

Change-Id: Id44c03f42fcd180950ccd008d4de0c144ea3597b
diff --git a/Android.bp b/Android.bp
index 273f87e..d77d318 100644
--- a/Android.bp
+++ b/Android.bp
@@ -128,12 +128,24 @@
         "cc/check.go",
         "cc/clang.go",
         "cc/gen.go",
+        "cc/global.go",
         "cc/makevars.go",
         "cc/sanitize.go",
         "cc/stl.go",
+        "cc/strip.go",
         "cc/toolchain.go",
         "cc/util.go",
 
+        "cc/compiler.go",
+        "cc/installer.go",
+        "cc/linker.go",
+
+        "cc/binary.go",
+        "cc/library.go",
+        "cc/object.go",
+        "cc/test.go",
+
+        "cc/ndk_prebuilt.go",
         "cc/ndk_headers.go",
         "cc/ndk_library.go",
         "cc/ndk_sysroot.go",
diff --git a/cc/binary.go b/cc/binary.go
new file mode 100644
index 0000000..d6b086c
--- /dev/null
+++ b/cc/binary.go
@@ -0,0 +1,282 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"github.com/google/blueprint"
+
+	"android/soong"
+	"android/soong/android"
+)
+
+type BinaryLinkerProperties struct {
+	// compile executable with -static
+	Static_executable *bool `android:"arch_variant"`
+
+	// set the name of the output
+	Stem string `android:"arch_variant"`
+
+	// append to the name of the output
+	Suffix string `android:"arch_variant"`
+
+	// if set, add an extra objcopy --prefix-symbols= step
+	Prefix_symbols string
+}
+
+func init() {
+	soong.RegisterModuleType("cc_binary", binaryFactory)
+	soong.RegisterModuleType("cc_binary_host", binaryHostFactory)
+}
+
+// Module factory for binaries
+func binaryFactory() (blueprint.Module, []interface{}) {
+	module := NewBinary(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+// Module factory for host binaries
+func binaryHostFactory() (blueprint.Module, []interface{}) {
+	module := NewBinary(android.HostSupported)
+	return module.Init()
+}
+
+//
+// Executables
+//
+
+type binaryLinker struct {
+	baseLinker
+	stripper
+
+	Properties BinaryLinkerProperties
+
+	hostToolPath android.OptionalPath
+}
+
+var _ linker = (*binaryLinker)(nil)
+
+func (binary *binaryLinker) props() []interface{} {
+	return append(binary.baseLinker.props(),
+		&binary.Properties,
+		&binary.stripper.StripProperties)
+
+}
+
+func (binary *binaryLinker) buildStatic() bool {
+	return binary.baseLinker.staticBinary()
+}
+
+func (binary *binaryLinker) buildShared() bool {
+	return !binary.baseLinker.staticBinary()
+}
+
+func (binary *binaryLinker) getStem(ctx BaseModuleContext) string {
+	stem := ctx.ModuleName()
+	if binary.Properties.Stem != "" {
+		stem = binary.Properties.Stem
+	}
+
+	return stem + binary.Properties.Suffix
+}
+
+func (binary *binaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps = binary.baseLinker.deps(ctx, deps)
+	if ctx.Device() {
+		if !Bool(binary.baseLinker.Properties.Nocrt) {
+			if !ctx.sdk() {
+				if binary.buildStatic() {
+					deps.CrtBegin = "crtbegin_static"
+				} else {
+					deps.CrtBegin = "crtbegin_dynamic"
+				}
+				deps.CrtEnd = "crtend_android"
+			} else {
+				if binary.buildStatic() {
+					deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
+				} else {
+					if Bool(binary.Properties.Static_executable) {
+						deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
+					} else {
+						deps.CrtBegin = "ndk_crtbegin_dynamic." + ctx.sdkVersion()
+					}
+					deps.CrtEnd = "ndk_crtend_android." + ctx.sdkVersion()
+				}
+			}
+		}
+
+		if binary.buildStatic() {
+			if inList("libc++_static", deps.StaticLibs) {
+				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
+			}
+			// static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
+			// --start-group/--end-group along with libgcc.  If they are in deps.StaticLibs,
+			// move them to the beginning of deps.LateStaticLibs
+			var groupLibs []string
+			deps.StaticLibs, groupLibs = filterList(deps.StaticLibs,
+				[]string{"libc", "libc_nomalloc", "libcompiler_rt"})
+			deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...)
+		}
+	}
+
+	if binary.buildShared() && inList("libc", deps.StaticLibs) {
+		ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
+			"from static libs or set static_executable: true")
+	}
+	return deps
+}
+
+func (*binaryLinker) installable() bool {
+	return true
+}
+
+func (binary *binaryLinker) isDependencyRoot() bool {
+	return true
+}
+
+func NewBinary(hod android.HostOrDeviceSupported) *Module {
+	module := newModule(hod, android.MultilibFirst)
+	module.compiler = &baseCompiler{}
+	module.linker = &binaryLinker{}
+	module.installer = &baseInstaller{
+		dir: "bin",
+	}
+	return module
+}
+
+func (binary *binaryLinker) begin(ctx BaseModuleContext) {
+	binary.baseLinker.begin(ctx)
+
+	static := Bool(binary.Properties.Static_executable)
+	if ctx.Host() {
+		if ctx.Os() == android.Linux {
+			if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) {
+				static = true
+			}
+		} else {
+			// Static executables are not supported on Darwin or Windows
+			static = false
+		}
+	}
+	if static {
+		binary.dynamicProperties.VariantIsStatic = true
+		binary.dynamicProperties.VariantIsStaticBinary = true
+	}
+}
+
+func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	flags = binary.baseLinker.flags(ctx, flags)
+
+	if ctx.Host() && !binary.staticBinary() {
+		flags.LdFlags = append(flags.LdFlags, "-pie")
+		if ctx.Os() == android.Windows {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
+		}
+	}
+
+	// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
+	// all code is position independent, and then those warnings get promoted to
+	// errors.
+	if ctx.Os() != android.Windows {
+		flags.CFlags = append(flags.CFlags, "-fpie")
+	}
+
+	if ctx.Device() {
+		if binary.buildStatic() {
+			// Clang driver needs -static to create static executable.
+			// However, bionic/linker uses -shared to overwrite.
+			// Linker for x86 targets does not allow coexistance of -static and -shared,
+			// so we add -static only if -shared is not used.
+			if !inList("-shared", flags.LdFlags) {
+				flags.LdFlags = append(flags.LdFlags, "-static")
+			}
+
+			flags.LdFlags = append(flags.LdFlags,
+				"-nostdlib",
+				"-Bstatic",
+				"-Wl,--gc-sections",
+			)
+
+		} else {
+			if flags.DynamicLinker == "" {
+				flags.DynamicLinker = "/system/bin/linker"
+				if flags.Toolchain.Is64Bit() {
+					flags.DynamicLinker += "64"
+				}
+			}
+
+			flags.LdFlags = append(flags.LdFlags,
+				"-pie",
+				"-nostdlib",
+				"-Bdynamic",
+				"-Wl,--gc-sections",
+				"-Wl,-z,nocopyreloc",
+			)
+		}
+	} else {
+		if binary.staticBinary() {
+			flags.LdFlags = append(flags.LdFlags, "-static")
+		}
+		if ctx.Darwin() {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
+		}
+	}
+
+	return flags
+}
+
+func (binary *binaryLinker) link(ctx ModuleContext,
+	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+	fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
+	outputFile := android.PathForModuleOut(ctx, fileName)
+	ret := outputFile
+	if ctx.Os().Class == android.Host {
+		binary.hostToolPath = android.OptionalPathForPath(outputFile)
+	}
+
+	var linkerDeps android.Paths
+
+	sharedLibs := deps.SharedLibs
+	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
+
+	if flags.DynamicLinker != "" {
+		flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
+	}
+
+	builderFlags := flagsToBuilderFlags(flags)
+
+	if binary.stripper.needsStrip(ctx) {
+		strippedOutputFile := outputFile
+		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
+		binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
+	}
+
+	if binary.Properties.Prefix_symbols != "" {
+		afterPrefixSymbols := outputFile
+		outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
+		TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
+			flagsToBuilderFlags(flags), afterPrefixSymbols)
+	}
+
+	TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
+		deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
+		builderFlags, outputFile)
+
+	return ret
+}
+
+func (binary *binaryLinker) HostToolPath() android.OptionalPath {
+	return binary.hostToolPath
+}
diff --git a/cc/cc.go b/cc/cc.go
index 12d9ed7..53345c5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -20,7 +20,6 @@
 
 import (
 	"fmt"
-	"path/filepath"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -32,27 +31,9 @@
 )
 
 func init() {
-	soong.RegisterModuleType("cc_library_static", libraryStaticFactory)
-	soong.RegisterModuleType("cc_library_shared", librarySharedFactory)
-	soong.RegisterModuleType("cc_library", libraryFactory)
-	soong.RegisterModuleType("cc_object", objectFactory)
-	soong.RegisterModuleType("cc_binary", binaryFactory)
-	soong.RegisterModuleType("cc_test", testFactory)
-	soong.RegisterModuleType("cc_test_library", testLibraryFactory)
-	soong.RegisterModuleType("cc_benchmark", benchmarkFactory)
 	soong.RegisterModuleType("cc_defaults", defaultsFactory)
 
 	soong.RegisterModuleType("toolchain_library", toolchainLibraryFactory)
-	soong.RegisterModuleType("ndk_prebuilt_library", ndkPrebuiltLibraryFactory)
-	soong.RegisterModuleType("ndk_prebuilt_object", ndkPrebuiltObjectFactory)
-	soong.RegisterModuleType("ndk_prebuilt_static_stl", ndkPrebuiltStaticStlFactory)
-	soong.RegisterModuleType("ndk_prebuilt_shared_stl", ndkPrebuiltSharedStlFactory)
-
-	soong.RegisterModuleType("cc_library_host_static", libraryHostStaticFactory)
-	soong.RegisterModuleType("cc_library_host_shared", libraryHostSharedFactory)
-	soong.RegisterModuleType("cc_binary_host", binaryHostFactory)
-	soong.RegisterModuleType("cc_test_host", testHostFactory)
-	soong.RegisterModuleType("cc_benchmark_host", benchmarkHostFactory)
 
 	// LinkageMutator must be registered after common.ArchMutator, but that is guaranteed by
 	// the Go initialization order because this package depends on common, so common's init
@@ -69,139 +50,6 @@
 	android.RegisterBottomUpMutator("tsan", sanitizerMutator(tsan))
 }
 
-var (
-	HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
-
-	// These libraries have migrated over to the new ndk_library, which is added
-	// as a variation dependency via depsMutator.
-	ndkMigratedLibs = []string{}
-)
-
-// Flags used by lots of devices.  Putting them in package static variables will save bytes in
-// build.ninja so they aren't repeated for every file
-var (
-	commonGlobalCflags = []string{
-		"-DANDROID",
-		"-fmessage-length=0",
-		"-W",
-		"-Wall",
-		"-Wno-unused",
-		"-Winit-self",
-		"-Wpointer-arith",
-
-		// COMMON_RELEASE_CFLAGS
-		"-DNDEBUG",
-		"-UDEBUG",
-	}
-
-	deviceGlobalCflags = []string{
-		"-fdiagnostics-color",
-
-		// TARGET_ERROR_FLAGS
-		"-Werror=return-type",
-		"-Werror=non-virtual-dtor",
-		"-Werror=address",
-		"-Werror=sequence-point",
-		"-Werror=date-time",
-	}
-
-	hostGlobalCflags = []string{}
-
-	commonGlobalCppflags = []string{
-		"-Wsign-promo",
-	}
-
-	noOverrideGlobalCflags = []string{
-		"-Werror=int-to-pointer-cast",
-		"-Werror=pointer-to-int-cast",
-	}
-
-	illegalFlags = []string{
-		"-w",
-	}
-
-	ndkPrebuiltSharedLibs = []string{
-		"android",
-		"c",
-		"dl",
-		"EGL",
-		"GLESv1_CM",
-		"GLESv2",
-		"GLESv3",
-		"jnigraphics",
-		"log",
-		"mediandk",
-		"m",
-		"OpenMAXAL",
-		"OpenSLES",
-		"stdc++",
-		"vulkan",
-		"z",
-	}
-	ndkPrebuiltSharedLibraries = addPrefix(append([]string(nil), ndkPrebuiltSharedLibs...), "lib")
-)
-
-func init() {
-	if android.BuildOs == android.Linux {
-		commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
-	}
-
-	pctx.StaticVariable("commonGlobalCflags", strings.Join(commonGlobalCflags, " "))
-	pctx.StaticVariable("deviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
-	pctx.StaticVariable("hostGlobalCflags", strings.Join(hostGlobalCflags, " "))
-	pctx.StaticVariable("noOverrideGlobalCflags", strings.Join(noOverrideGlobalCflags, " "))
-
-	pctx.StaticVariable("commonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
-
-	pctx.StaticVariable("commonClangGlobalCflags",
-		strings.Join(append(clangFilterUnknownCflags(commonGlobalCflags), "${clangExtraCflags}"), " "))
-	pctx.StaticVariable("deviceClangGlobalCflags",
-		strings.Join(append(clangFilterUnknownCflags(deviceGlobalCflags), "${clangExtraTargetCflags}"), " "))
-	pctx.StaticVariable("hostClangGlobalCflags",
-		strings.Join(clangFilterUnknownCflags(hostGlobalCflags), " "))
-	pctx.StaticVariable("noOverrideClangGlobalCflags",
-		strings.Join(append(clangFilterUnknownCflags(noOverrideGlobalCflags), "${clangExtraNoOverrideCflags}"), " "))
-
-	pctx.StaticVariable("commonClangGlobalCppflags",
-		strings.Join(append(clangFilterUnknownCflags(commonGlobalCppflags), "${clangExtraCppflags}"), " "))
-
-	// Everything in this list is a crime against abstraction and dependency tracking.
-	// Do not add anything to this list.
-	pctx.PrefixedPathsForOptionalSourceVariable("commonGlobalIncludes", "-isystem ",
-		[]string{
-			"system/core/include",
-			"system/media/audio/include",
-			"hardware/libhardware/include",
-			"hardware/libhardware_legacy/include",
-			"hardware/ril/include",
-			"libnativehelper/include",
-			"frameworks/native/include",
-			"frameworks/native/opengl/include",
-			"frameworks/av/include",
-			"frameworks/base/include",
-		})
-	// This is used by non-NDK modules to get jni.h. export_include_dirs doesn't help
-	// with this, since there is no associated library.
-	pctx.PrefixedPathsForOptionalSourceVariable("commonNativehelperInclude", "-I",
-		[]string{"libnativehelper/include/nativehelper"})
-
-	pctx.SourcePathVariable("clangDefaultBase", "prebuilts/clang/host")
-	pctx.VariableFunc("clangBase", func(config interface{}) (string, error) {
-		if override := config.(android.Config).Getenv("LLVM_PREBUILTS_BASE"); override != "" {
-			return override, nil
-		}
-		return "${clangDefaultBase}", nil
-	})
-	pctx.VariableFunc("clangVersion", func(config interface{}) (string, error) {
-		if override := config.(android.Config).Getenv("LLVM_PREBUILTS_VERSION"); override != "" {
-			return override, nil
-		}
-		return "clang-3016494", nil
-	})
-	pctx.StaticVariable("clangPath", "${clangBase}/${HostPrebuiltTag}/${clangVersion}")
-	pctx.StaticVariable("clangBin", "${clangPath}/bin")
-}
-
 type Deps struct {
 	SharedLibs, LateSharedLibs                  []string
 	StaticLibs, LateStaticLibs, WholeStaticLibs []string
@@ -251,191 +99,6 @@
 	CFlagsDeps android.Paths // Files depended on by compiler flags
 }
 
-type BaseCompilerProperties struct {
-	// list of source files used to compile the C/C++ module.  May be .c, .cpp, or .S files.
-	Srcs []string `android:"arch_variant"`
-
-	// list of source files that should not be used to build the C/C++ module.
-	// This is most useful in the arch/multilib variants to remove non-common files
-	Exclude_srcs []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for C and C++ compiles.
-	Cflags []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for C++ compiles
-	Cppflags []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for C compiles
-	Conlyflags []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for .S compiles
-	Asflags []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for C and C++ compiles when
-	// compiling with clang
-	Clang_cflags []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for .S compiles when
-	// compiling with clang
-	Clang_asflags []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for .y and .yy compiles
-	Yaccflags []string
-
-	// the instruction set architecture to use to compile the C/C++
-	// module.
-	Instruction_set string `android:"arch_variant"`
-
-	// list of directories relative to the root of the source tree that will
-	// be added to the include path using -I.
-	// If possible, don't use this.  If adding paths from the current directory use
-	// local_include_dirs, if adding paths from other modules use export_include_dirs in
-	// that module.
-	Include_dirs []string `android:"arch_variant"`
-
-	// list of directories relative to the Blueprints file that will
-	// be added to the include path using -I
-	Local_include_dirs []string `android:"arch_variant"`
-
-	// list of generated sources to compile. These are the names of gensrcs or
-	// genrule modules.
-	Generated_sources []string `android:"arch_variant"`
-
-	// list of generated headers to add to the include path. These are the names
-	// of genrule modules.
-	Generated_headers []string `android:"arch_variant"`
-
-	// pass -frtti instead of -fno-rtti
-	Rtti *bool
-
-	Debug, Release struct {
-		// list of module-specific flags that will be used for C and C++ compiles in debug or
-		// release builds
-		Cflags []string `android:"arch_variant"`
-	} `android:"arch_variant"`
-}
-
-type BaseLinkerProperties struct {
-	// list of modules whose object files should be linked into this module
-	// in their entirety.  For static library modules, all of the .o files from the intermediate
-	// directory of the dependency will be linked into this modules .a file.  For a shared library,
-	// the dependency's .a file will be linked into this module using -Wl,--whole-archive.
-	Whole_static_libs []string `android:"arch_variant,variant_prepend"`
-
-	// list of modules that should be statically linked into this module.
-	Static_libs []string `android:"arch_variant,variant_prepend"`
-
-	// list of modules that should be dynamically linked into this module.
-	Shared_libs []string `android:"arch_variant"`
-
-	// list of module-specific flags that will be used for all link steps
-	Ldflags []string `android:"arch_variant"`
-
-	// don't insert default compiler flags into asflags, cflags,
-	// cppflags, conlyflags, ldflags, or include_dirs
-	No_default_compiler_flags *bool
-
-	// list of system libraries that will be dynamically linked to
-	// shared library and executable modules.  If unset, generally defaults to libc
-	// and libm.  Set to [] to prevent linking against libc and libm.
-	System_shared_libs []string
-
-	// allow the module to contain undefined symbols.  By default,
-	// modules cannot contain undefined symbols that are not satisified by their immediate
-	// dependencies.  Set this flag to true to remove --no-undefined from the linker flags.
-	// This flag should only be necessary for compiling low-level libraries like libc.
-	Allow_undefined_symbols *bool
-
-	// don't link in libgcc.a
-	No_libgcc *bool
-
-	// -l arguments to pass to linker for host-provided shared libraries
-	Host_ldlibs []string `android:"arch_variant"`
-
-	// list of shared libraries to re-export include directories from. Entries must be
-	// present in shared_libs.
-	Export_shared_lib_headers []string `android:"arch_variant"`
-
-	// list of static libraries to re-export include directories from. Entries must be
-	// present in static_libs.
-	Export_static_lib_headers []string `android:"arch_variant"`
-
-	// don't link in crt_begin and crt_end.  This flag should only be necessary for
-	// compiling crt or libc.
-	Nocrt *bool `android:"arch_variant"`
-}
-
-type LibraryCompilerProperties struct {
-	Static struct {
-		Srcs         []string `android:"arch_variant"`
-		Exclude_srcs []string `android:"arch_variant"`
-		Cflags       []string `android:"arch_variant"`
-	} `android:"arch_variant"`
-	Shared struct {
-		Srcs         []string `android:"arch_variant"`
-		Exclude_srcs []string `android:"arch_variant"`
-		Cflags       []string `android:"arch_variant"`
-	} `android:"arch_variant"`
-}
-
-type FlagExporterProperties struct {
-	// list of directories relative to the Blueprints file that will
-	// be added to the include path using -I for any module that links against this module
-	Export_include_dirs []string `android:"arch_variant"`
-}
-
-type LibraryLinkerProperties struct {
-	Static struct {
-		Enabled           *bool    `android:"arch_variant"`
-		Whole_static_libs []string `android:"arch_variant"`
-		Static_libs       []string `android:"arch_variant"`
-		Shared_libs       []string `android:"arch_variant"`
-	} `android:"arch_variant"`
-	Shared struct {
-		Enabled           *bool    `android:"arch_variant"`
-		Whole_static_libs []string `android:"arch_variant"`
-		Static_libs       []string `android:"arch_variant"`
-		Shared_libs       []string `android:"arch_variant"`
-	} `android:"arch_variant"`
-
-	// local file name to pass to the linker as --version_script
-	Version_script *string `android:"arch_variant"`
-	// local file name to pass to the linker as -unexported_symbols_list
-	Unexported_symbols_list *string `android:"arch_variant"`
-	// local file name to pass to the linker as -force_symbols_not_weak_list
-	Force_symbols_not_weak_list *string `android:"arch_variant"`
-	// local file name to pass to the linker as -force_symbols_weak_list
-	Force_symbols_weak_list *string `android:"arch_variant"`
-
-	// rename host libraries to prevent overlap with system installed libraries
-	Unique_host_soname *bool
-
-	VariantName string `blueprint:"mutated"`
-}
-
-type BinaryLinkerProperties struct {
-	// compile executable with -static
-	Static_executable *bool `android:"arch_variant"`
-
-	// set the name of the output
-	Stem string `android:"arch_variant"`
-
-	// append to the name of the output
-	Suffix string `android:"arch_variant"`
-
-	// if set, add an extra objcopy --prefix-symbols= step
-	Prefix_symbols string
-}
-
-type TestLinkerProperties struct {
-	// if set, build against the gtest library. Defaults to true.
-	Gtest bool
-
-	// Create a separate binary for each source file.  Useful when there is
-	// global state that can not be torn down and reset between each test suite.
-	Test_per_src *bool
-}
-
 type ObjectLinkerProperties struct {
 	// names of other cc_object modules to link into this module using partial linking
 	Objs []string `android:"arch_variant"`
@@ -457,21 +120,6 @@
 	HideFromMake        bool     `blueprint:"mutated"`
 }
 
-type InstallerProperties struct {
-	// install to a subdirectory of the default install path for the module
-	Relative_install_path string
-
-	// install symlinks to the module
-	Symlinks []string `android:"arch_variant"`
-}
-
-type StripProperties struct {
-	Strip struct {
-		None         bool
-		Keep_symbols bool
-	}
-}
-
 type UnusedProperties struct {
 	Native_coverage *bool
 	Required        []string
@@ -1161,1394 +809,6 @@
 	return c.installer.inData()
 }
 
-// Compiler
-
-type baseCompiler struct {
-	Properties BaseCompilerProperties
-}
-
-var _ compiler = (*baseCompiler)(nil)
-
-func (compiler *baseCompiler) appendCflags(flags []string) {
-	compiler.Properties.Cflags = append(compiler.Properties.Cflags, flags...)
-}
-
-func (compiler *baseCompiler) appendAsflags(flags []string) {
-	compiler.Properties.Asflags = append(compiler.Properties.Asflags, flags...)
-}
-
-func (compiler *baseCompiler) props() []interface{} {
-	return []interface{}{&compiler.Properties}
-}
-
-func (compiler *baseCompiler) begin(ctx BaseModuleContext) {}
-
-func (compiler *baseCompiler) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
-	deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
-
-	return deps
-}
-
-// Create a Flags struct that collects the compile flags from global values,
-// per-target values, module type values, and per-module Blueprints properties
-func (compiler *baseCompiler) flags(ctx ModuleContext, flags Flags) Flags {
-	toolchain := ctx.toolchain()
-
-	CheckBadCompilerFlags(ctx, "cflags", compiler.Properties.Cflags)
-	CheckBadCompilerFlags(ctx, "cppflags", compiler.Properties.Cppflags)
-	CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags)
-	CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
-
-	flags.CFlags = append(flags.CFlags, compiler.Properties.Cflags...)
-	flags.CppFlags = append(flags.CppFlags, compiler.Properties.Cppflags...)
-	flags.ConlyFlags = append(flags.ConlyFlags, compiler.Properties.Conlyflags...)
-	flags.AsFlags = append(flags.AsFlags, compiler.Properties.Asflags...)
-	flags.YaccFlags = append(flags.YaccFlags, compiler.Properties.Yaccflags...)
-
-	// Include dir cflags
-	rootIncludeDirs := android.PathsForSource(ctx, compiler.Properties.Include_dirs)
-	localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs)
-	flags.GlobalFlags = append(flags.GlobalFlags,
-		includeDirsToFlags(localIncludeDirs),
-		includeDirsToFlags(rootIncludeDirs))
-
-	if !ctx.noDefaultCompilerFlags() {
-		if !ctx.sdk() || ctx.Host() {
-			flags.GlobalFlags = append(flags.GlobalFlags,
-				"${commonGlobalIncludes}",
-				toolchain.IncludeFlags(),
-				"${commonNativehelperInclude}")
-		}
-
-		flags.GlobalFlags = append(flags.GlobalFlags, []string{
-			"-I" + android.PathForModuleSrc(ctx).String(),
-			"-I" + android.PathForModuleOut(ctx).String(),
-			"-I" + android.PathForModuleGen(ctx).String(),
-		}...)
-	}
-
-	if ctx.sdk() {
-		// The NDK headers are installed to a common sysroot. While a more
-		// typical Soong approach would be to only make the headers for the
-		// library you're using available, we're trying to emulate the NDK
-		// behavior here, and the NDK always has all the NDK headers available.
-		flags.GlobalFlags = append(flags.GlobalFlags,
-			"-isystem "+getCurrentIncludePath(ctx).String(),
-			"-isystem "+getCurrentIncludePath(ctx).Join(ctx, toolchain.ClangTriple()).String())
-
-		// Traditionally this has come from android/api-level.h, but with the
-		// libc headers unified it must be set by the build system since we
-		// don't have per-API level copies of that header now.
-		flags.GlobalFlags = append(flags.GlobalFlags,
-			"-D__ANDROID_API__="+ctx.sdkVersion())
-
-		// Until the full NDK has been migrated to using ndk_headers, we still
-		// need to add the legacy sysroot includes to get the full set of
-		// headers.
-		legacyIncludes := fmt.Sprintf(
-			"prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/include",
-			ctx.sdkVersion(), ctx.Arch().ArchType.String())
-		flags.GlobalFlags = append(flags.GlobalFlags, "-isystem "+legacyIncludes)
-	}
-
-	instructionSet := compiler.Properties.Instruction_set
-	if flags.RequiredInstructionSet != "" {
-		instructionSet = flags.RequiredInstructionSet
-	}
-	instructionSetFlags, err := toolchain.InstructionSetFlags(instructionSet)
-	if flags.Clang {
-		instructionSetFlags, err = toolchain.ClangInstructionSetFlags(instructionSet)
-	}
-	if err != nil {
-		ctx.ModuleErrorf("%s", err)
-	}
-
-	CheckBadCompilerFlags(ctx, "release.cflags", compiler.Properties.Release.Cflags)
-
-	// TODO: debug
-	flags.CFlags = append(flags.CFlags, compiler.Properties.Release.Cflags...)
-
-	if flags.Clang {
-		CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
-		CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
-
-		flags.CFlags = clangFilterUnknownCflags(flags.CFlags)
-		flags.CFlags = append(flags.CFlags, compiler.Properties.Clang_cflags...)
-		flags.AsFlags = append(flags.AsFlags, compiler.Properties.Clang_asflags...)
-		flags.CppFlags = clangFilterUnknownCflags(flags.CppFlags)
-		flags.ConlyFlags = clangFilterUnknownCflags(flags.ConlyFlags)
-		flags.LdFlags = clangFilterUnknownCflags(flags.LdFlags)
-
-		target := "-target " + toolchain.ClangTriple()
-		var gccPrefix string
-		if !ctx.Darwin() {
-			gccPrefix = "-B" + filepath.Join(toolchain.GccRoot(), toolchain.GccTriple(), "bin")
-		}
-
-		flags.CFlags = append(flags.CFlags, target, gccPrefix)
-		flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
-		flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
-	}
-
-	hod := "host"
-	if ctx.Os().Class == android.Device {
-		hod = "device"
-	}
-
-	if !ctx.noDefaultCompilerFlags() {
-		flags.GlobalFlags = append(flags.GlobalFlags, instructionSetFlags)
-
-		if flags.Clang {
-			flags.AsFlags = append(flags.AsFlags, toolchain.ClangAsflags())
-			flags.CppFlags = append(flags.CppFlags, "${commonClangGlobalCppflags}")
-			flags.GlobalFlags = append(flags.GlobalFlags,
-				toolchain.ClangCflags(),
-				"${commonClangGlobalCflags}",
-				fmt.Sprintf("${%sClangGlobalCflags}", hod))
-
-			flags.ConlyFlags = append(flags.ConlyFlags, "${clangExtraConlyflags}")
-		} else {
-			flags.CppFlags = append(flags.CppFlags, "${commonGlobalCppflags}")
-			flags.GlobalFlags = append(flags.GlobalFlags,
-				toolchain.Cflags(),
-				"${commonGlobalCflags}",
-				fmt.Sprintf("${%sGlobalCflags}", hod))
-		}
-
-		if Bool(ctx.AConfig().ProductVariables.Brillo) {
-			flags.GlobalFlags = append(flags.GlobalFlags, "-D__BRILLO__")
-		}
-
-		if ctx.Device() {
-			if Bool(compiler.Properties.Rtti) {
-				flags.CppFlags = append(flags.CppFlags, "-frtti")
-			} else {
-				flags.CppFlags = append(flags.CppFlags, "-fno-rtti")
-			}
-		}
-
-		flags.AsFlags = append(flags.AsFlags, "-D__ASSEMBLY__")
-
-		if flags.Clang {
-			flags.CppFlags = append(flags.CppFlags, toolchain.ClangCppflags())
-		} else {
-			flags.CppFlags = append(flags.CppFlags, toolchain.Cppflags())
-		}
-	}
-
-	if flags.Clang {
-		flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainClangCflags())
-	} else {
-		flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainCflags())
-	}
-
-	if !ctx.sdk() {
-		if ctx.Host() && !flags.Clang {
-			// The host GCC doesn't support C++14 (and is deprecated, so likely
-			// never will). Build these modules with C++11.
-			flags.CppFlags = append(flags.CppFlags, "-std=gnu++11")
-		} else {
-			flags.CppFlags = append(flags.CppFlags, "-std=gnu++14")
-		}
-	}
-
-	// We can enforce some rules more strictly in the code we own. strict
-	// indicates if this is code that we can be stricter with. If we have
-	// rules that we want to apply to *our* code (but maybe can't for
-	// vendor/device specific things), we could extend this to be a ternary
-	// value.
-	strict := true
-	if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
-		strict = false
-	}
-
-	// Can be used to make some annotations stricter for code we can fix
-	// (such as when we mark functions as deprecated).
-	if strict {
-		flags.CFlags = append(flags.CFlags, "-DANDROID_STRICT")
-	}
-
-	return flags
-}
-
-func ndkPathDeps(ctx ModuleContext) android.Paths {
-	if ctx.sdk() {
-		// The NDK sysroot timestamp file depends on all the NDK sysroot files
-		// (headers and libraries).
-		return android.Paths{getNdkSysrootTimestampFile(ctx)}
-	}
-	return nil
-}
-
-func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
-	pathDeps := deps.GeneratedHeaders
-	pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
-	// Compile files listed in c.Properties.Srcs into objects
-	objFiles := compiler.compileObjs(ctx, flags, "",
-		compiler.Properties.Srcs, compiler.Properties.Exclude_srcs,
-		deps.GeneratedSources, pathDeps)
-
-	if ctx.Failed() {
-		return nil
-	}
-
-	return objFiles
-}
-
-// Compile a list of source files into objects a specified subdirectory
-func (compiler *baseCompiler) compileObjs(ctx android.ModuleContext, flags Flags,
-	subdir string, srcFiles, excludes []string, extraSrcs, deps android.Paths) android.Paths {
-
-	buildFlags := flagsToBuilderFlags(flags)
-
-	inputFiles := ctx.ExpandSources(srcFiles, excludes)
-	inputFiles = append(inputFiles, extraSrcs...)
-	srcPaths, gendeps := genSources(ctx, inputFiles, buildFlags)
-
-	deps = append(deps, gendeps...)
-	deps = append(deps, flags.CFlagsDeps...)
-
-	return TransformSourceToObj(ctx, subdir, srcPaths, buildFlags, deps)
-}
-
-// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
-type baseLinker struct {
-	Properties        BaseLinkerProperties
-	dynamicProperties struct {
-		VariantIsShared       bool     `blueprint:"mutated"`
-		VariantIsStatic       bool     `blueprint:"mutated"`
-		VariantIsStaticBinary bool     `blueprint:"mutated"`
-		RunPaths              []string `blueprint:"mutated"`
-	}
-}
-
-func (linker *baseLinker) appendLdflags(flags []string) {
-	linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
-}
-
-func (linker *baseLinker) begin(ctx BaseModuleContext) {
-	if ctx.toolchain().Is64Bit() {
-		linker.dynamicProperties.RunPaths = []string{"../lib64", "lib64"}
-	} else {
-		linker.dynamicProperties.RunPaths = []string{"../lib", "lib"}
-	}
-}
-
-func (linker *baseLinker) props() []interface{} {
-	return []interface{}{&linker.Properties, &linker.dynamicProperties}
-}
-
-func (linker *baseLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
-	deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
-	deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
-
-	deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...)
-	deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
-
-	if !ctx.sdk() && ctx.ModuleName() != "libcompiler_rt-extras" {
-		deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras")
-	}
-
-	if ctx.Device() {
-		// libgcc and libatomic have to be last on the command line
-		deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
-		if !Bool(linker.Properties.No_libgcc) {
-			deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
-		}
-
-		if !linker.static() {
-			if linker.Properties.System_shared_libs != nil {
-				deps.LateSharedLibs = append(deps.LateSharedLibs,
-					linker.Properties.System_shared_libs...)
-			} else if !ctx.sdk() {
-				deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm")
-			}
-		}
-
-		if ctx.sdk() {
-			deps.SharedLibs = append(deps.SharedLibs,
-				"libc",
-				"libm",
-			)
-		}
-	}
-
-	return deps
-}
-
-func (linker *baseLinker) flags(ctx ModuleContext, flags Flags) Flags {
-	toolchain := ctx.toolchain()
-
-	flags.Nocrt = Bool(linker.Properties.Nocrt)
-
-	if !ctx.noDefaultCompilerFlags() {
-		if ctx.Device() && !Bool(linker.Properties.Allow_undefined_symbols) {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
-		}
-
-		if flags.Clang {
-			flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
-		} else {
-			flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
-		}
-
-		if ctx.Host() {
-			CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
-
-			flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...)
-		}
-	}
-
-	CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
-
-	flags.LdFlags = append(flags.LdFlags, linker.Properties.Ldflags...)
-
-	if ctx.Host() && !linker.static() {
-		rpath_prefix := `\$$ORIGIN/`
-		if ctx.Darwin() {
-			rpath_prefix = "@loader_path/"
-		}
-
-		for _, rpath := range linker.dynamicProperties.RunPaths {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
-		}
-	}
-
-	if flags.Clang {
-		flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
-	} else {
-		flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
-	}
-
-	return flags
-}
-
-func (linker *baseLinker) static() bool {
-	return linker.dynamicProperties.VariantIsStatic
-}
-
-func (linker *baseLinker) staticBinary() bool {
-	return linker.dynamicProperties.VariantIsStaticBinary
-}
-
-func (linker *baseLinker) setStatic(static bool) {
-	linker.dynamicProperties.VariantIsStatic = static
-}
-
-func (linker *baseLinker) isDependencyRoot() bool {
-	return false
-}
-
-type baseLinkerInterface interface {
-	// Returns true if the build options for the module have selected a static or shared build
-	buildStatic() bool
-	buildShared() bool
-
-	// Sets whether a specific variant is static or shared
-	setStatic(bool)
-
-	// Returns whether a specific variant is a static library or binary
-	static() bool
-
-	// Returns whether a module is a static binary
-	staticBinary() bool
-
-	// Returns true for dependency roots (binaries)
-	// TODO(ccross): also handle dlopenable libraries
-	isDependencyRoot() bool
-}
-
-type baseInstaller struct {
-	Properties InstallerProperties
-
-	dir   string
-	dir64 string
-	data  bool
-
-	path android.OutputPath
-}
-
-var _ installer = (*baseInstaller)(nil)
-
-func (installer *baseInstaller) props() []interface{} {
-	return []interface{}{&installer.Properties}
-}
-
-func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
-	subDir := installer.dir
-	if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
-		subDir = installer.dir64
-	}
-	if !ctx.Host() && !ctx.Arch().Native {
-		subDir = filepath.Join(subDir, ctx.Arch().ArchType.String())
-	}
-	dir := android.PathForModuleInstall(ctx, subDir, installer.Properties.Relative_install_path)
-	installer.path = ctx.InstallFile(dir, file)
-	for _, symlink := range installer.Properties.Symlinks {
-		ctx.InstallSymlink(dir, symlink, installer.path)
-	}
-}
-
-func (installer *baseInstaller) inData() bool {
-	return installer.data
-}
-
-//
-// Combined static+shared libraries
-//
-
-type flagExporter struct {
-	Properties FlagExporterProperties
-
-	flags []string
-}
-
-func (f *flagExporter) exportIncludes(ctx ModuleContext, inc string) {
-	includeDirs := android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
-	for _, dir := range includeDirs.Strings() {
-		f.flags = append(f.flags, inc+dir)
-	}
-}
-
-func (f *flagExporter) reexportFlags(flags []string) {
-	f.flags = append(f.flags, flags...)
-}
-
-func (f *flagExporter) exportedFlags() []string {
-	return f.flags
-}
-
-type exportedFlagsProducer interface {
-	exportedFlags() []string
-}
-
-var _ exportedFlagsProducer = (*flagExporter)(nil)
-
-type libraryCompiler struct {
-	baseCompiler
-
-	linker     *libraryLinker
-	Properties LibraryCompilerProperties
-
-	// For reusing static library objects for shared library
-	reuseObjFiles android.Paths
-}
-
-var _ compiler = (*libraryCompiler)(nil)
-
-func (library *libraryCompiler) props() []interface{} {
-	props := library.baseCompiler.props()
-	return append(props, &library.Properties)
-}
-
-func (library *libraryCompiler) flags(ctx ModuleContext, flags Flags) Flags {
-	flags = library.baseCompiler.flags(ctx, flags)
-
-	// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
-	// all code is position independent, and then those warnings get promoted to
-	// errors.
-	if ctx.Os() != android.Windows {
-		flags.CFlags = append(flags.CFlags, "-fPIC")
-	}
-
-	if library.linker.static() {
-		flags.CFlags = append(flags.CFlags, library.Properties.Static.Cflags...)
-	} else {
-		flags.CFlags = append(flags.CFlags, library.Properties.Shared.Cflags...)
-	}
-
-	return flags
-}
-
-func (library *libraryCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
-	var objFiles android.Paths
-
-	objFiles = library.baseCompiler.compile(ctx, flags, deps)
-	library.reuseObjFiles = objFiles
-
-	pathDeps := deps.GeneratedHeaders
-	pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
-
-	if library.linker.static() {
-		objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceStaticLibrary,
-			library.Properties.Static.Srcs, library.Properties.Static.Exclude_srcs,
-			nil, pathDeps)...)
-	} else {
-		objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceSharedLibrary,
-			library.Properties.Shared.Srcs, library.Properties.Shared.Exclude_srcs,
-			nil, pathDeps)...)
-	}
-
-	return objFiles
-}
-
-type libraryLinker struct {
-	baseLinker
-	flagExporter
-	stripper
-
-	Properties LibraryLinkerProperties
-
-	dynamicProperties struct {
-		BuildStatic bool `blueprint:"mutated"`
-		BuildShared bool `blueprint:"mutated"`
-	}
-
-	// If we're used as a whole_static_lib, our missing dependencies need
-	// to be given
-	wholeStaticMissingDeps []string
-
-	// For whole_static_libs
-	objFiles android.Paths
-
-	// Uses the module's name if empty, but can be overridden. Does not include
-	// shlib suffix.
-	libName string
-}
-
-var _ linker = (*libraryLinker)(nil)
-
-type libraryInterface interface {
-	getWholeStaticMissingDeps() []string
-	static() bool
-	objs() android.Paths
-}
-
-func (library *libraryLinker) props() []interface{} {
-	props := library.baseLinker.props()
-	return append(props,
-		&library.Properties,
-		&library.dynamicProperties,
-		&library.flagExporter.Properties,
-		&library.stripper.StripProperties)
-}
-
-func (library *libraryLinker) getLibName(ctx ModuleContext) string {
-	name := library.libName
-	if name == "" {
-		name = ctx.ModuleName()
-	}
-
-	if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
-		if !strings.HasSuffix(name, "-host") {
-			name = name + "-host"
-		}
-	}
-
-	return name + library.Properties.VariantName
-}
-
-func (library *libraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
-	flags = library.baseLinker.flags(ctx, flags)
-
-	if !library.static() {
-		libName := library.getLibName(ctx)
-		// GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
-		sharedFlag := "-Wl,-shared"
-		if flags.Clang || ctx.Host() {
-			sharedFlag = "-shared"
-		}
-		var f []string
-		if ctx.Device() {
-			f = append(f,
-				"-nostdlib",
-				"-Wl,--gc-sections",
-			)
-		}
-
-		if ctx.Darwin() {
-			f = append(f,
-				"-dynamiclib",
-				"-single_module",
-				//"-read_only_relocs suppress",
-				"-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(),
-			)
-		} else {
-			f = append(f,
-				sharedFlag,
-				"-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
-		}
-
-		flags.LdFlags = append(f, flags.LdFlags...)
-	}
-
-	return flags
-}
-
-func (library *libraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps = library.baseLinker.deps(ctx, deps)
-	if library.static() {
-		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Static.Whole_static_libs...)
-		deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
-		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
-	} else {
-		if ctx.Device() && !Bool(library.baseLinker.Properties.Nocrt) {
-			if !ctx.sdk() {
-				deps.CrtBegin = "crtbegin_so"
-				deps.CrtEnd = "crtend_so"
-			} else {
-				deps.CrtBegin = "ndk_crtbegin_so." + ctx.sdkVersion()
-				deps.CrtEnd = "ndk_crtend_so." + ctx.sdkVersion()
-			}
-		}
-		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
-		deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
-		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
-	}
-
-	return deps
-}
-
-func (library *libraryLinker) linkStatic(ctx ModuleContext,
-	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
-	library.objFiles = append(android.Paths{}, deps.WholeStaticLibObjFiles...)
-	library.objFiles = append(library.objFiles, objFiles...)
-
-	outputFile := android.PathForModuleOut(ctx,
-		ctx.ModuleName()+library.Properties.VariantName+staticLibraryExtension)
-
-	if ctx.Darwin() {
-		TransformDarwinObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
-	} else {
-		TransformObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
-	}
-
-	library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
-
-	ctx.CheckbuildFile(outputFile)
-
-	return outputFile
-}
-
-func (library *libraryLinker) linkShared(ctx ModuleContext,
-	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
-	var linkerDeps android.Paths
-
-	versionScript := android.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
-	unexportedSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Unexported_symbols_list)
-	forceNotWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_not_weak_list)
-	forceWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_weak_list)
-	if !ctx.Darwin() {
-		if versionScript.Valid() {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
-			linkerDeps = append(linkerDeps, versionScript.Path())
-		}
-		if unexportedSymbols.Valid() {
-			ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
-		}
-		if forceNotWeakSymbols.Valid() {
-			ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
-		}
-		if forceWeakSymbols.Valid() {
-			ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
-		}
-	} else {
-		if versionScript.Valid() {
-			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
-		}
-		if unexportedSymbols.Valid() {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
-			linkerDeps = append(linkerDeps, unexportedSymbols.Path())
-		}
-		if forceNotWeakSymbols.Valid() {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
-			linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
-		}
-		if forceWeakSymbols.Valid() {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
-			linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
-		}
-	}
-
-	fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
-	outputFile := android.PathForModuleOut(ctx, fileName)
-	ret := outputFile
-
-	builderFlags := flagsToBuilderFlags(flags)
-
-	if library.stripper.needsStrip(ctx) {
-		strippedOutputFile := outputFile
-		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
-		library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
-	}
-
-	sharedLibs := deps.SharedLibs
-	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
-
-	TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
-		deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
-		linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
-
-	return ret
-}
-
-func (library *libraryLinker) link(ctx ModuleContext,
-	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
-	objFiles = append(objFiles, deps.ObjFiles...)
-
-	var out android.Path
-	if library.static() {
-		out = library.linkStatic(ctx, flags, deps, objFiles)
-	} else {
-		out = library.linkShared(ctx, flags, deps, objFiles)
-	}
-
-	library.exportIncludes(ctx, "-I")
-	library.reexportFlags(deps.ReexportedFlags)
-
-	return out
-}
-
-func (library *libraryLinker) buildStatic() bool {
-	return library.dynamicProperties.BuildStatic &&
-		(library.Properties.Static.Enabled == nil || *library.Properties.Static.Enabled)
-}
-
-func (library *libraryLinker) buildShared() bool {
-	return library.dynamicProperties.BuildShared &&
-		(library.Properties.Shared.Enabled == nil || *library.Properties.Shared.Enabled)
-}
-
-func (library *libraryLinker) getWholeStaticMissingDeps() []string {
-	return library.wholeStaticMissingDeps
-}
-
-func (library *libraryLinker) installable() bool {
-	return !library.static()
-}
-
-func (library *libraryLinker) objs() android.Paths {
-	return library.objFiles
-}
-
-type libraryInstaller struct {
-	baseInstaller
-
-	linker   *libraryLinker
-	sanitize *sanitize
-}
-
-func (library *libraryInstaller) install(ctx ModuleContext, file android.Path) {
-	if !library.linker.static() {
-		library.baseInstaller.install(ctx, file)
-	}
-}
-
-func (library *libraryInstaller) inData() bool {
-	return library.baseInstaller.inData() || library.sanitize.inData()
-}
-
-func NewLibrary(hod android.HostOrDeviceSupported, shared, static bool) *Module {
-	module := newModule(hod, android.MultilibBoth)
-
-	linker := &libraryLinker{}
-	linker.dynamicProperties.BuildShared = shared
-	linker.dynamicProperties.BuildStatic = static
-	module.linker = linker
-
-	module.compiler = &libraryCompiler{
-		linker: linker,
-	}
-	module.installer = &libraryInstaller{
-		baseInstaller: baseInstaller{
-			dir:   "lib",
-			dir64: "lib64",
-		},
-		linker:   linker,
-		sanitize: module.sanitize,
-	}
-
-	return module
-}
-
-func libraryFactory() (blueprint.Module, []interface{}) {
-	module := NewLibrary(android.HostAndDeviceSupported, true, true)
-	return module.Init()
-}
-
-//
-// Objects (for crt*.o)
-//
-
-type objectLinker struct {
-	Properties ObjectLinkerProperties
-}
-
-func objectFactory() (blueprint.Module, []interface{}) {
-	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	module.compiler = &baseCompiler{}
-	module.linker = &objectLinker{}
-	return module.Init()
-}
-
-func (object *objectLinker) appendLdflags(flags []string) {
-	panic(fmt.Errorf("appendLdflags on object Linker not supported"))
-}
-
-func (object *objectLinker) props() []interface{} {
-	return []interface{}{&object.Properties}
-}
-
-func (*objectLinker) begin(ctx BaseModuleContext) {}
-
-func (object *objectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
-	return deps
-}
-
-func (*objectLinker) flags(ctx ModuleContext, flags Flags) Flags {
-	if flags.Clang {
-		flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
-	} else {
-		flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainLdflags())
-	}
-
-	return flags
-}
-
-func (object *objectLinker) link(ctx ModuleContext,
-	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
-	objFiles = append(objFiles, deps.ObjFiles...)
-
-	var outputFile android.Path
-	if len(objFiles) == 1 {
-		outputFile = objFiles[0]
-	} else {
-		output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
-		TransformObjsToObj(ctx, objFiles, flagsToBuilderFlags(flags), output)
-		outputFile = output
-	}
-
-	ctx.CheckbuildFile(outputFile)
-	return outputFile
-}
-
-func (*objectLinker) installable() bool {
-	return false
-}
-
-//
-// Executables
-//
-
-type binaryLinker struct {
-	baseLinker
-	stripper
-
-	Properties BinaryLinkerProperties
-
-	hostToolPath android.OptionalPath
-}
-
-var _ linker = (*binaryLinker)(nil)
-
-func (binary *binaryLinker) props() []interface{} {
-	return append(binary.baseLinker.props(),
-		&binary.Properties,
-		&binary.stripper.StripProperties)
-
-}
-
-func (binary *binaryLinker) buildStatic() bool {
-	return binary.baseLinker.staticBinary()
-}
-
-func (binary *binaryLinker) buildShared() bool {
-	return !binary.baseLinker.staticBinary()
-}
-
-func (binary *binaryLinker) getStem(ctx BaseModuleContext) string {
-	stem := ctx.ModuleName()
-	if binary.Properties.Stem != "" {
-		stem = binary.Properties.Stem
-	}
-
-	return stem + binary.Properties.Suffix
-}
-
-func (binary *binaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps = binary.baseLinker.deps(ctx, deps)
-	if ctx.Device() {
-		if !Bool(binary.baseLinker.Properties.Nocrt) {
-			if !ctx.sdk() {
-				if binary.buildStatic() {
-					deps.CrtBegin = "crtbegin_static"
-				} else {
-					deps.CrtBegin = "crtbegin_dynamic"
-				}
-				deps.CrtEnd = "crtend_android"
-			} else {
-				if binary.buildStatic() {
-					deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
-				} else {
-					if Bool(binary.Properties.Static_executable) {
-						deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
-					} else {
-						deps.CrtBegin = "ndk_crtbegin_dynamic." + ctx.sdkVersion()
-					}
-					deps.CrtEnd = "ndk_crtend_android." + ctx.sdkVersion()
-				}
-			}
-		}
-
-		if binary.buildStatic() {
-			if inList("libc++_static", deps.StaticLibs) {
-				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
-			}
-			// static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
-			// --start-group/--end-group along with libgcc.  If they are in deps.StaticLibs,
-			// move them to the beginning of deps.LateStaticLibs
-			var groupLibs []string
-			deps.StaticLibs, groupLibs = filterList(deps.StaticLibs,
-				[]string{"libc", "libc_nomalloc", "libcompiler_rt"})
-			deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...)
-		}
-	}
-
-	if binary.buildShared() && inList("libc", deps.StaticLibs) {
-		ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
-			"from static libs or set static_executable: true")
-	}
-	return deps
-}
-
-func (*binaryLinker) installable() bool {
-	return true
-}
-
-func (binary *binaryLinker) isDependencyRoot() bool {
-	return true
-}
-
-func NewBinary(hod android.HostOrDeviceSupported) *Module {
-	module := newModule(hod, android.MultilibFirst)
-	module.compiler = &baseCompiler{}
-	module.linker = &binaryLinker{}
-	module.installer = &baseInstaller{
-		dir: "bin",
-	}
-	return module
-}
-
-func binaryFactory() (blueprint.Module, []interface{}) {
-	module := NewBinary(android.HostAndDeviceSupported)
-	return module.Init()
-}
-
-func (binary *binaryLinker) begin(ctx BaseModuleContext) {
-	binary.baseLinker.begin(ctx)
-
-	static := Bool(binary.Properties.Static_executable)
-	if ctx.Host() {
-		if ctx.Os() == android.Linux {
-			if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) {
-				static = true
-			}
-		} else {
-			// Static executables are not supported on Darwin or Windows
-			static = false
-		}
-	}
-	if static {
-		binary.dynamicProperties.VariantIsStatic = true
-		binary.dynamicProperties.VariantIsStaticBinary = true
-	}
-}
-
-func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
-	flags = binary.baseLinker.flags(ctx, flags)
-
-	if ctx.Host() && !binary.staticBinary() {
-		flags.LdFlags = append(flags.LdFlags, "-pie")
-		if ctx.Os() == android.Windows {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
-		}
-	}
-
-	// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
-	// all code is position independent, and then those warnings get promoted to
-	// errors.
-	if ctx.Os() != android.Windows {
-		flags.CFlags = append(flags.CFlags, "-fpie")
-	}
-
-	if ctx.Device() {
-		if binary.buildStatic() {
-			// Clang driver needs -static to create static executable.
-			// However, bionic/linker uses -shared to overwrite.
-			// Linker for x86 targets does not allow coexistance of -static and -shared,
-			// so we add -static only if -shared is not used.
-			if !inList("-shared", flags.LdFlags) {
-				flags.LdFlags = append(flags.LdFlags, "-static")
-			}
-
-			flags.LdFlags = append(flags.LdFlags,
-				"-nostdlib",
-				"-Bstatic",
-				"-Wl,--gc-sections",
-			)
-
-		} else {
-			if flags.DynamicLinker == "" {
-				flags.DynamicLinker = "/system/bin/linker"
-				if flags.Toolchain.Is64Bit() {
-					flags.DynamicLinker += "64"
-				}
-			}
-
-			flags.LdFlags = append(flags.LdFlags,
-				"-pie",
-				"-nostdlib",
-				"-Bdynamic",
-				"-Wl,--gc-sections",
-				"-Wl,-z,nocopyreloc",
-			)
-		}
-	} else {
-		if binary.staticBinary() {
-			flags.LdFlags = append(flags.LdFlags, "-static")
-		}
-		if ctx.Darwin() {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
-		}
-	}
-
-	return flags
-}
-
-func (binary *binaryLinker) link(ctx ModuleContext,
-	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
-	fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
-	outputFile := android.PathForModuleOut(ctx, fileName)
-	ret := outputFile
-	if ctx.Os().Class == android.Host {
-		binary.hostToolPath = android.OptionalPathForPath(outputFile)
-	}
-
-	var linkerDeps android.Paths
-
-	sharedLibs := deps.SharedLibs
-	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
-
-	if flags.DynamicLinker != "" {
-		flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
-	}
-
-	builderFlags := flagsToBuilderFlags(flags)
-
-	if binary.stripper.needsStrip(ctx) {
-		strippedOutputFile := outputFile
-		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
-		binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
-	}
-
-	if binary.Properties.Prefix_symbols != "" {
-		afterPrefixSymbols := outputFile
-		outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
-		TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
-			flagsToBuilderFlags(flags), afterPrefixSymbols)
-	}
-
-	TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
-		deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
-		builderFlags, outputFile)
-
-	return ret
-}
-
-func (binary *binaryLinker) HostToolPath() android.OptionalPath {
-	return binary.hostToolPath
-}
-
-type stripper struct {
-	StripProperties StripProperties
-}
-
-func (stripper *stripper) needsStrip(ctx ModuleContext) bool {
-	return !ctx.AConfig().EmbeddedInMake() && !stripper.StripProperties.Strip.None
-}
-
-func (stripper *stripper) strip(ctx ModuleContext, in, out android.ModuleOutPath,
-	flags builderFlags) {
-	if ctx.Darwin() {
-		TransformDarwinStrip(ctx, in, out)
-	} else {
-		flags.stripKeepSymbols = stripper.StripProperties.Strip.Keep_symbols
-		// TODO(ccross): don't add gnu debuglink for user builds
-		flags.stripAddGnuDebuglink = true
-		TransformStrip(ctx, in, out, flags)
-	}
-}
-
-func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(*Module); ok {
-		if test, ok := m.linker.(*testBinaryLinker); ok {
-			if Bool(test.testLinker.Properties.Test_per_src) {
-				testNames := make([]string, len(m.compiler.(*baseCompiler).Properties.Srcs))
-				for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
-					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
-				}
-				tests := mctx.CreateLocalVariations(testNames...)
-				for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
-					tests[i].(*Module).compiler.(*baseCompiler).Properties.Srcs = []string{src}
-					tests[i].(*Module).linker.(*testBinaryLinker).binaryLinker.Properties.Stem = testNames[i]
-				}
-			}
-		}
-	}
-}
-
-type testLinker struct {
-	Properties TestLinkerProperties
-}
-
-func (test *testLinker) flags(ctx ModuleContext, flags Flags) Flags {
-	if !test.Properties.Gtest {
-		return flags
-	}
-
-	flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING")
-	if ctx.Host() {
-		flags.CFlags = append(flags.CFlags, "-O0", "-g")
-
-		switch ctx.Os() {
-		case android.Windows:
-			flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS")
-		case android.Linux:
-			flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX")
-			flags.LdFlags = append(flags.LdFlags, "-lpthread")
-		case android.Darwin:
-			flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC")
-			flags.LdFlags = append(flags.LdFlags, "-lpthread")
-		}
-	} else {
-		flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID")
-	}
-
-	return flags
-}
-
-func (test *testLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	if test.Properties.Gtest {
-		if ctx.sdk() && ctx.Device() {
-			switch ctx.selectedStl() {
-			case "ndk_libc++_shared", "ndk_libc++_static":
-				deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
-			case "ndk_libgnustl_static":
-				deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_gnustl", "libgtest_ndk_gnustl")
-			default:
-				deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk", "libgtest_ndk")
-			}
-		} else {
-			deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
-		}
-	}
-	return deps
-}
-
-type testBinaryLinker struct {
-	testLinker
-	binaryLinker
-}
-
-func (test *testBinaryLinker) begin(ctx BaseModuleContext) {
-	test.binaryLinker.begin(ctx)
-	runpath := "../../lib"
-	if ctx.toolchain().Is64Bit() {
-		runpath += "64"
-	}
-	test.dynamicProperties.RunPaths = append([]string{runpath}, test.dynamicProperties.RunPaths...)
-}
-
-func (test *testBinaryLinker) props() []interface{} {
-	return append(test.binaryLinker.props(), &test.testLinker.Properties)
-}
-
-func (test *testBinaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
-	flags = test.binaryLinker.flags(ctx, flags)
-	flags = test.testLinker.flags(ctx, flags)
-	return flags
-}
-
-func (test *testBinaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps = test.testLinker.deps(ctx, deps)
-	deps = test.binaryLinker.deps(ctx, deps)
-	return deps
-}
-
-type testLibraryLinker struct {
-	testLinker
-	*libraryLinker
-}
-
-func (test *testLibraryLinker) props() []interface{} {
-	return append(test.libraryLinker.props(), &test.testLinker.Properties)
-}
-
-func (test *testLibraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
-	flags = test.libraryLinker.flags(ctx, flags)
-	flags = test.testLinker.flags(ctx, flags)
-	return flags
-}
-
-func (test *testLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps = test.testLinker.deps(ctx, deps)
-	deps = test.libraryLinker.deps(ctx, deps)
-	return deps
-}
-
-type testInstaller struct {
-	baseInstaller
-}
-
-func (installer *testInstaller) install(ctx ModuleContext, file android.Path) {
-	installer.dir = filepath.Join(installer.dir, ctx.ModuleName())
-	installer.dir64 = filepath.Join(installer.dir64, ctx.ModuleName())
-	installer.baseInstaller.install(ctx, file)
-}
-
-func NewTest(hod android.HostOrDeviceSupported) *Module {
-	module := newModule(hod, android.MultilibBoth)
-	module.compiler = &baseCompiler{}
-	linker := &testBinaryLinker{}
-	linker.testLinker.Properties.Gtest = true
-	module.linker = linker
-	module.installer = &testInstaller{
-		baseInstaller: baseInstaller{
-			dir:   "nativetest",
-			dir64: "nativetest64",
-			data:  true,
-		},
-	}
-	return module
-}
-
-func testFactory() (blueprint.Module, []interface{}) {
-	module := NewTest(android.HostAndDeviceSupported)
-	return module.Init()
-}
-
-func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
-	module := NewLibrary(android.HostAndDeviceSupported, false, true)
-	linker := &testLibraryLinker{
-		libraryLinker: module.linker.(*libraryLinker),
-	}
-	linker.testLinker.Properties.Gtest = true
-	module.linker = linker
-	module.installer = &testInstaller{
-		baseInstaller: baseInstaller{
-			dir:   "nativetest",
-			dir64: "nativetest64",
-			data:  true,
-		},
-	}
-	return module
-}
-
-func testLibraryFactory() (blueprint.Module, []interface{}) {
-	module := NewTestLibrary(android.HostAndDeviceSupported)
-	return module.Init()
-}
-
-type benchmarkLinker struct {
-	testBinaryLinker
-}
-
-func (benchmark *benchmarkLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	deps = benchmark.testBinaryLinker.deps(ctx, deps)
-	deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
-	return deps
-}
-
-func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
-	module := newModule(hod, android.MultilibFirst)
-	module.compiler = &baseCompiler{}
-	module.linker = &benchmarkLinker{}
-	module.installer = &testInstaller{
-		baseInstaller: baseInstaller{
-			dir:   "nativetest",
-			dir64: "nativetest64",
-			data:  true,
-		},
-	}
-	return module
-}
-
-func benchmarkFactory() (blueprint.Module, []interface{}) {
-	module := NewBenchmark(android.HostAndDeviceSupported)
-	return module.Init()
-}
-
-//
-// Static library
-//
-
-func libraryStaticFactory() (blueprint.Module, []interface{}) {
-	module := NewLibrary(android.HostAndDeviceSupported, false, true)
-	return module.Init()
-}
-
-//
-// Shared libraries
-//
-
-func librarySharedFactory() (blueprint.Module, []interface{}) {
-	module := NewLibrary(android.HostAndDeviceSupported, true, false)
-	return module.Init()
-}
-
-//
-// Host static library
-//
-
-func libraryHostStaticFactory() (blueprint.Module, []interface{}) {
-	module := NewLibrary(android.HostSupported, false, true)
-	return module.Init()
-}
-
-//
-// Host Shared libraries
-//
-
-func libraryHostSharedFactory() (blueprint.Module, []interface{}) {
-	module := NewLibrary(android.HostSupported, true, false)
-	return module.Init()
-}
-
-//
-// Host Binaries
-//
-
-func binaryHostFactory() (blueprint.Module, []interface{}) {
-	module := NewBinary(android.HostSupported)
-	return module.Init()
-}
-
-//
-// Host Tests
-//
-
-func testHostFactory() (blueprint.Module, []interface{}) {
-	module := NewTest(android.HostSupported)
-	return module.Init()
-}
-
-//
-// Host Benchmarks
-//
-
-func benchmarkHostFactory() (blueprint.Module, []interface{}) {
-	module := NewBenchmark(android.HostSupported)
-	return module.Init()
-}
-
 //
 // Defaults
 //
@@ -2636,198 +896,6 @@
 	return false
 }
 
-// NDK prebuilt libraries.
-//
-// These differ from regular prebuilts in that they aren't stripped and usually aren't installed
-// either (with the exception of the shared STLs, which are installed to the app's directory rather
-// than to the system image).
-
-func getNdkLibDir(ctx android.ModuleContext, toolchain Toolchain, version string) android.SourcePath {
-	suffix := ""
-	// Most 64-bit NDK prebuilts store libraries in "lib64", except for arm64 which is not a
-	// multilib toolchain and stores the libraries in "lib".
-	if toolchain.Is64Bit() && ctx.Arch().ArchType != android.Arm64 {
-		suffix = "64"
-	}
-	return android.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib%s",
-		version, toolchain.Name(), suffix))
-}
-
-func ndkPrebuiltModuleToPath(ctx android.ModuleContext, toolchain Toolchain,
-	ext string, version string) android.Path {
-
-	// NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
-	// We want to translate to just NAME.EXT
-	name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
-	dir := getNdkLibDir(ctx, toolchain, version)
-	return dir.Join(ctx, name+ext)
-}
-
-type ndkPrebuiltObjectLinker struct {
-	objectLinker
-}
-
-func (*ndkPrebuiltObjectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	// NDK objects can't have any dependencies
-	return deps
-}
-
-func ndkPrebuiltObjectFactory() (blueprint.Module, []interface{}) {
-	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	module.linker = &ndkPrebuiltObjectLinker{}
-	module.Properties.HideFromMake = true
-	return module.Init()
-}
-
-func (c *ndkPrebuiltObjectLinker) link(ctx ModuleContext, flags Flags,
-	deps PathDeps, objFiles android.Paths) android.Path {
-	// A null build step, but it sets up the output path.
-	if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
-		ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name")
-	}
-
-	return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion())
-}
-
-type ndkPrebuiltLibraryLinker struct {
-	libraryLinker
-}
-
-var _ baseLinkerInterface = (*ndkPrebuiltLibraryLinker)(nil)
-var _ exportedFlagsProducer = (*libraryLinker)(nil)
-
-func (ndk *ndkPrebuiltLibraryLinker) props() []interface{} {
-	return append(ndk.libraryLinker.props(), &ndk.Properties, &ndk.flagExporter.Properties)
-}
-
-func (*ndkPrebuiltLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
-	// NDK libraries can't have any dependencies
-	return deps
-}
-
-func ndkPrebuiltLibraryFactory() (blueprint.Module, []interface{}) {
-	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	linker := &ndkPrebuiltLibraryLinker{}
-	linker.dynamicProperties.BuildShared = true
-	module.linker = linker
-	module.Properties.HideFromMake = true
-	return module.Init()
-}
-
-func (ndk *ndkPrebuiltLibraryLinker) link(ctx ModuleContext, flags Flags,
-	deps PathDeps, objFiles android.Paths) android.Path {
-	// A null build step, but it sets up the output path.
-	ndk.exportIncludes(ctx, "-isystem")
-
-	return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),
-		ctx.sdkVersion())
-}
-
-// The NDK STLs are slightly different from the prebuilt system libraries:
-//     * Are not specific to each platform version.
-//     * The libraries are not in a predictable location for each STL.
-
-type ndkPrebuiltStlLinker struct {
-	ndkPrebuiltLibraryLinker
-}
-
-func ndkPrebuiltSharedStlFactory() (blueprint.Module, []interface{}) {
-	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	linker := &ndkPrebuiltStlLinker{}
-	linker.dynamicProperties.BuildShared = true
-	module.linker = linker
-	module.Properties.HideFromMake = true
-	return module.Init()
-}
-
-func ndkPrebuiltStaticStlFactory() (blueprint.Module, []interface{}) {
-	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	linker := &ndkPrebuiltStlLinker{}
-	linker.dynamicProperties.BuildStatic = true
-	module.linker = linker
-	module.Properties.HideFromMake = true
-	return module.Init()
-}
-
-func getNdkStlLibDir(ctx android.ModuleContext, toolchain Toolchain, stl string) android.SourcePath {
-	gccVersion := toolchain.GccVersion()
-	var libDir string
-	switch stl {
-	case "libstlport":
-		libDir = "cxx-stl/stlport/libs"
-	case "libc++":
-		libDir = "cxx-stl/llvm-libc++/libs"
-	case "libgnustl":
-		libDir = fmt.Sprintf("cxx-stl/gnu-libstdc++/%s/libs", gccVersion)
-	}
-
-	if libDir != "" {
-		ndkSrcRoot := "prebuilts/ndk/current/sources"
-		return android.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0])
-	}
-
-	ctx.ModuleErrorf("Unknown NDK STL: %s", stl)
-	return android.PathForSource(ctx, "")
-}
-
-func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
-	deps PathDeps, objFiles android.Paths) android.Path {
-	// A null build step, but it sets up the output path.
-	if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
-		ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
-	}
-
-	ndk.exportIncludes(ctx, "-I")
-
-	libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
-	libExt := flags.Toolchain.ShlibSuffix()
-	if ndk.dynamicProperties.BuildStatic {
-		libExt = staticLibraryExtension
-	}
-
-	stlName := strings.TrimSuffix(libName, "_shared")
-	stlName = strings.TrimSuffix(stlName, "_static")
-	libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName)
-	return libDir.Join(ctx, libName+libExt)
-}
-
-func linkageMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(*Module); ok {
-		if m.linker != nil {
-			if linker, ok := m.linker.(baseLinkerInterface); ok {
-				var modules []blueprint.Module
-				if linker.buildStatic() && linker.buildShared() {
-					modules = mctx.CreateLocalVariations("static", "shared")
-					static := modules[0].(*Module)
-					shared := modules[1].(*Module)
-
-					static.linker.(baseLinkerInterface).setStatic(true)
-					shared.linker.(baseLinkerInterface).setStatic(false)
-
-					if staticCompiler, ok := static.compiler.(*libraryCompiler); ok {
-						sharedCompiler := shared.compiler.(*libraryCompiler)
-						if len(staticCompiler.Properties.Static.Cflags) == 0 &&
-							len(sharedCompiler.Properties.Shared.Cflags) == 0 {
-							// Optimize out compiling common .o files twice for static+shared libraries
-							mctx.AddInterVariantDependency(reuseObjTag, shared, static)
-							sharedCompiler.baseCompiler.Properties.Srcs = nil
-							sharedCompiler.baseCompiler.Properties.Generated_sources = nil
-						}
-					}
-				} else if linker.buildStatic() {
-					modules = mctx.CreateLocalVariations("static")
-					modules[0].(*Module).linker.(baseLinkerInterface).setStatic(true)
-				} else if linker.buildShared() {
-					modules = mctx.CreateLocalVariations("shared")
-					modules[0].(*Module).linker.(baseLinkerInterface).setStatic(false)
-				} else {
-					panic(fmt.Errorf("library %q not static or shared", mctx.ModuleName()))
-				}
-			}
-		}
-	}
-}
-
 // lastUniqueElements returns all unique elements of a slice, keeping the last copy of each
 // modifies the slice contents in place, and returns a subslice of the original slice
 func lastUniqueElements(list []string) []string {
diff --git a/cc/compiler.go b/cc/compiler.go
new file mode 100644
index 0000000..8fcab8f
--- /dev/null
+++ b/cc/compiler.go
@@ -0,0 +1,338 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"fmt"
+	"path/filepath"
+	"strings"
+
+	"android/soong/android"
+)
+
+// This file contains the basic C/C++/assembly to .o compliation steps
+
+type BaseCompilerProperties struct {
+	// list of source files used to compile the C/C++ module.  May be .c, .cpp, or .S files.
+	Srcs []string `android:"arch_variant"`
+
+	// list of source files that should not be used to build the C/C++ module.
+	// This is most useful in the arch/multilib variants to remove non-common files
+	Exclude_srcs []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for C and C++ compiles.
+	Cflags []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for C++ compiles
+	Cppflags []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for C compiles
+	Conlyflags []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for .S compiles
+	Asflags []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for C and C++ compiles when
+	// compiling with clang
+	Clang_cflags []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for .S compiles when
+	// compiling with clang
+	Clang_asflags []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for .y and .yy compiles
+	Yaccflags []string
+
+	// the instruction set architecture to use to compile the C/C++
+	// module.
+	Instruction_set string `android:"arch_variant"`
+
+	// list of directories relative to the root of the source tree that will
+	// be added to the include path using -I.
+	// If possible, don't use this.  If adding paths from the current directory use
+	// local_include_dirs, if adding paths from other modules use export_include_dirs in
+	// that module.
+	Include_dirs []string `android:"arch_variant"`
+
+	// list of directories relative to the Blueprints file that will
+	// be added to the include path using -I
+	Local_include_dirs []string `android:"arch_variant"`
+
+	// list of generated sources to compile. These are the names of gensrcs or
+	// genrule modules.
+	Generated_sources []string `android:"arch_variant"`
+
+	// list of generated headers to add to the include path. These are the names
+	// of genrule modules.
+	Generated_headers []string `android:"arch_variant"`
+
+	// pass -frtti instead of -fno-rtti
+	Rtti *bool
+
+	Debug, Release struct {
+		// list of module-specific flags that will be used for C and C++ compiles in debug or
+		// release builds
+		Cflags []string `android:"arch_variant"`
+	} `android:"arch_variant"`
+}
+
+type baseCompiler struct {
+	Properties BaseCompilerProperties
+}
+
+var _ compiler = (*baseCompiler)(nil)
+
+func (compiler *baseCompiler) appendCflags(flags []string) {
+	compiler.Properties.Cflags = append(compiler.Properties.Cflags, flags...)
+}
+
+func (compiler *baseCompiler) appendAsflags(flags []string) {
+	compiler.Properties.Asflags = append(compiler.Properties.Asflags, flags...)
+}
+
+func (compiler *baseCompiler) props() []interface{} {
+	return []interface{}{&compiler.Properties}
+}
+
+func (compiler *baseCompiler) begin(ctx BaseModuleContext) {}
+
+func (compiler *baseCompiler) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
+	deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
+
+	return deps
+}
+
+// Create a Flags struct that collects the compile flags from global values,
+// per-target values, module type values, and per-module Blueprints properties
+func (compiler *baseCompiler) flags(ctx ModuleContext, flags Flags) Flags {
+	toolchain := ctx.toolchain()
+
+	CheckBadCompilerFlags(ctx, "cflags", compiler.Properties.Cflags)
+	CheckBadCompilerFlags(ctx, "cppflags", compiler.Properties.Cppflags)
+	CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags)
+	CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
+
+	flags.CFlags = append(flags.CFlags, compiler.Properties.Cflags...)
+	flags.CppFlags = append(flags.CppFlags, compiler.Properties.Cppflags...)
+	flags.ConlyFlags = append(flags.ConlyFlags, compiler.Properties.Conlyflags...)
+	flags.AsFlags = append(flags.AsFlags, compiler.Properties.Asflags...)
+	flags.YaccFlags = append(flags.YaccFlags, compiler.Properties.Yaccflags...)
+
+	// Include dir cflags
+	rootIncludeDirs := android.PathsForSource(ctx, compiler.Properties.Include_dirs)
+	localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs)
+	flags.GlobalFlags = append(flags.GlobalFlags,
+		includeDirsToFlags(localIncludeDirs),
+		includeDirsToFlags(rootIncludeDirs))
+
+	if !ctx.noDefaultCompilerFlags() {
+		if !ctx.sdk() || ctx.Host() {
+			flags.GlobalFlags = append(flags.GlobalFlags,
+				"${commonGlobalIncludes}",
+				toolchain.IncludeFlags(),
+				"${commonNativehelperInclude}")
+		}
+
+		flags.GlobalFlags = append(flags.GlobalFlags, []string{
+			"-I" + android.PathForModuleSrc(ctx).String(),
+			"-I" + android.PathForModuleOut(ctx).String(),
+			"-I" + android.PathForModuleGen(ctx).String(),
+		}...)
+	}
+
+	if ctx.sdk() {
+		// The NDK headers are installed to a common sysroot. While a more
+		// typical Soong approach would be to only make the headers for the
+		// library you're using available, we're trying to emulate the NDK
+		// behavior here, and the NDK always has all the NDK headers available.
+		flags.GlobalFlags = append(flags.GlobalFlags,
+			"-isystem "+getCurrentIncludePath(ctx).String(),
+			"-isystem "+getCurrentIncludePath(ctx).Join(ctx, toolchain.ClangTriple()).String())
+
+		// Traditionally this has come from android/api-level.h, but with the
+		// libc headers unified it must be set by the build system since we
+		// don't have per-API level copies of that header now.
+		flags.GlobalFlags = append(flags.GlobalFlags,
+			"-D__ANDROID_API__="+ctx.sdkVersion())
+
+		// Until the full NDK has been migrated to using ndk_headers, we still
+		// need to add the legacy sysroot includes to get the full set of
+		// headers.
+		legacyIncludes := fmt.Sprintf(
+			"prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/include",
+			ctx.sdkVersion(), ctx.Arch().ArchType.String())
+		flags.GlobalFlags = append(flags.GlobalFlags, "-isystem "+legacyIncludes)
+	}
+
+	instructionSet := compiler.Properties.Instruction_set
+	if flags.RequiredInstructionSet != "" {
+		instructionSet = flags.RequiredInstructionSet
+	}
+	instructionSetFlags, err := toolchain.InstructionSetFlags(instructionSet)
+	if flags.Clang {
+		instructionSetFlags, err = toolchain.ClangInstructionSetFlags(instructionSet)
+	}
+	if err != nil {
+		ctx.ModuleErrorf("%s", err)
+	}
+
+	CheckBadCompilerFlags(ctx, "release.cflags", compiler.Properties.Release.Cflags)
+
+	// TODO: debug
+	flags.CFlags = append(flags.CFlags, compiler.Properties.Release.Cflags...)
+
+	if flags.Clang {
+		CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
+		CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+
+		flags.CFlags = clangFilterUnknownCflags(flags.CFlags)
+		flags.CFlags = append(flags.CFlags, compiler.Properties.Clang_cflags...)
+		flags.AsFlags = append(flags.AsFlags, compiler.Properties.Clang_asflags...)
+		flags.CppFlags = clangFilterUnknownCflags(flags.CppFlags)
+		flags.ConlyFlags = clangFilterUnknownCflags(flags.ConlyFlags)
+		flags.LdFlags = clangFilterUnknownCflags(flags.LdFlags)
+
+		target := "-target " + toolchain.ClangTriple()
+		var gccPrefix string
+		if !ctx.Darwin() {
+			gccPrefix = "-B" + filepath.Join(toolchain.GccRoot(), toolchain.GccTriple(), "bin")
+		}
+
+		flags.CFlags = append(flags.CFlags, target, gccPrefix)
+		flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
+		flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
+	}
+
+	hod := "host"
+	if ctx.Os().Class == android.Device {
+		hod = "device"
+	}
+
+	if !ctx.noDefaultCompilerFlags() {
+		flags.GlobalFlags = append(flags.GlobalFlags, instructionSetFlags)
+
+		if flags.Clang {
+			flags.AsFlags = append(flags.AsFlags, toolchain.ClangAsflags())
+			flags.CppFlags = append(flags.CppFlags, "${commonClangGlobalCppflags}")
+			flags.GlobalFlags = append(flags.GlobalFlags,
+				toolchain.ClangCflags(),
+				"${commonClangGlobalCflags}",
+				fmt.Sprintf("${%sClangGlobalCflags}", hod))
+
+			flags.ConlyFlags = append(flags.ConlyFlags, "${clangExtraConlyflags}")
+		} else {
+			flags.CppFlags = append(flags.CppFlags, "${commonGlobalCppflags}")
+			flags.GlobalFlags = append(flags.GlobalFlags,
+				toolchain.Cflags(),
+				"${commonGlobalCflags}",
+				fmt.Sprintf("${%sGlobalCflags}", hod))
+		}
+
+		if Bool(ctx.AConfig().ProductVariables.Brillo) {
+			flags.GlobalFlags = append(flags.GlobalFlags, "-D__BRILLO__")
+		}
+
+		if ctx.Device() {
+			if Bool(compiler.Properties.Rtti) {
+				flags.CppFlags = append(flags.CppFlags, "-frtti")
+			} else {
+				flags.CppFlags = append(flags.CppFlags, "-fno-rtti")
+			}
+		}
+
+		flags.AsFlags = append(flags.AsFlags, "-D__ASSEMBLY__")
+
+		if flags.Clang {
+			flags.CppFlags = append(flags.CppFlags, toolchain.ClangCppflags())
+		} else {
+			flags.CppFlags = append(flags.CppFlags, toolchain.Cppflags())
+		}
+	}
+
+	if flags.Clang {
+		flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainClangCflags())
+	} else {
+		flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainCflags())
+	}
+
+	if !ctx.sdk() {
+		if ctx.Host() && !flags.Clang {
+			// The host GCC doesn't support C++14 (and is deprecated, so likely
+			// never will). Build these modules with C++11.
+			flags.CppFlags = append(flags.CppFlags, "-std=gnu++11")
+		} else {
+			flags.CppFlags = append(flags.CppFlags, "-std=gnu++14")
+		}
+	}
+
+	// We can enforce some rules more strictly in the code we own. strict
+	// indicates if this is code that we can be stricter with. If we have
+	// rules that we want to apply to *our* code (but maybe can't for
+	// vendor/device specific things), we could extend this to be a ternary
+	// value.
+	strict := true
+	if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
+		strict = false
+	}
+
+	// Can be used to make some annotations stricter for code we can fix
+	// (such as when we mark functions as deprecated).
+	if strict {
+		flags.CFlags = append(flags.CFlags, "-DANDROID_STRICT")
+	}
+
+	return flags
+}
+
+func ndkPathDeps(ctx ModuleContext) android.Paths {
+	if ctx.sdk() {
+		// The NDK sysroot timestamp file depends on all the NDK sysroot files
+		// (headers and libraries).
+		return android.Paths{getNdkSysrootTimestampFile(ctx)}
+	}
+	return nil
+}
+
+func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
+	pathDeps := deps.GeneratedHeaders
+	pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
+	// Compile files listed in c.Properties.Srcs into objects
+	objFiles := compiler.compileObjs(ctx, flags, "",
+		compiler.Properties.Srcs, compiler.Properties.Exclude_srcs,
+		deps.GeneratedSources, pathDeps)
+
+	if ctx.Failed() {
+		return nil
+	}
+
+	return objFiles
+}
+
+// Compile a list of source files into objects a specified subdirectory
+func (compiler *baseCompiler) compileObjs(ctx android.ModuleContext, flags Flags,
+	subdir string, srcFiles, excludes []string, extraSrcs, deps android.Paths) android.Paths {
+
+	buildFlags := flagsToBuilderFlags(flags)
+
+	inputFiles := ctx.ExpandSources(srcFiles, excludes)
+	inputFiles = append(inputFiles, extraSrcs...)
+	srcPaths, gendeps := genSources(ctx, inputFiles, buildFlags)
+
+	deps = append(deps, gendeps...)
+	deps = append(deps, flags.CFlagsDeps...)
+
+	return TransformSourceToObj(ctx, subdir, srcPaths, buildFlags, deps)
+}
diff --git a/cc/global.go b/cc/global.go
new file mode 100644
index 0000000..ec0f572
--- /dev/null
+++ b/cc/global.go
@@ -0,0 +1,138 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+// Flags used by lots of devices.  Putting them in package static variables will save bytes in
+// build.ninja so they aren't repeated for every file
+var (
+	commonGlobalCflags = []string{
+		"-DANDROID",
+		"-fmessage-length=0",
+		"-W",
+		"-Wall",
+		"-Wno-unused",
+		"-Winit-self",
+		"-Wpointer-arith",
+
+		// COMMON_RELEASE_CFLAGS
+		"-DNDEBUG",
+		"-UDEBUG",
+	}
+
+	deviceGlobalCflags = []string{
+		"-fdiagnostics-color",
+
+		// TARGET_ERROR_FLAGS
+		"-Werror=return-type",
+		"-Werror=non-virtual-dtor",
+		"-Werror=address",
+		"-Werror=sequence-point",
+		"-Werror=date-time",
+	}
+
+	hostGlobalCflags = []string{}
+
+	commonGlobalCppflags = []string{
+		"-Wsign-promo",
+	}
+
+	noOverrideGlobalCflags = []string{
+		"-Werror=int-to-pointer-cast",
+		"-Werror=pointer-to-int-cast",
+	}
+
+	illegalFlags = []string{
+		"-w",
+	}
+)
+
+func init() {
+	if android.BuildOs == android.Linux {
+		commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
+	}
+
+	pctx.StaticVariable("commonGlobalCflags", strings.Join(commonGlobalCflags, " "))
+	pctx.StaticVariable("deviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
+	pctx.StaticVariable("hostGlobalCflags", strings.Join(hostGlobalCflags, " "))
+	pctx.StaticVariable("noOverrideGlobalCflags", strings.Join(noOverrideGlobalCflags, " "))
+
+	pctx.StaticVariable("commonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
+
+	pctx.StaticVariable("commonClangGlobalCflags",
+		strings.Join(append(clangFilterUnknownCflags(commonGlobalCflags), "${clangExtraCflags}"), " "))
+	pctx.StaticVariable("deviceClangGlobalCflags",
+		strings.Join(append(clangFilterUnknownCflags(deviceGlobalCflags), "${clangExtraTargetCflags}"), " "))
+	pctx.StaticVariable("hostClangGlobalCflags",
+		strings.Join(clangFilterUnknownCflags(hostGlobalCflags), " "))
+	pctx.StaticVariable("noOverrideClangGlobalCflags",
+		strings.Join(append(clangFilterUnknownCflags(noOverrideGlobalCflags), "${clangExtraNoOverrideCflags}"), " "))
+
+	pctx.StaticVariable("commonClangGlobalCppflags",
+		strings.Join(append(clangFilterUnknownCflags(commonGlobalCppflags), "${clangExtraCppflags}"), " "))
+
+	// Everything in this list is a crime against abstraction and dependency tracking.
+	// Do not add anything to this list.
+	pctx.PrefixedPathsForOptionalSourceVariable("commonGlobalIncludes", "-isystem ",
+		[]string{
+			"system/core/include",
+			"system/media/audio/include",
+			"hardware/libhardware/include",
+			"hardware/libhardware_legacy/include",
+			"hardware/ril/include",
+			"libnativehelper/include",
+			"frameworks/native/include",
+			"frameworks/native/opengl/include",
+			"frameworks/av/include",
+			"frameworks/base/include",
+		})
+	// This is used by non-NDK modules to get jni.h. export_include_dirs doesn't help
+	// with this, since there is no associated library.
+	pctx.PrefixedPathsForOptionalSourceVariable("commonNativehelperInclude", "-I",
+		[]string{"libnativehelper/include/nativehelper"})
+
+	pctx.SourcePathVariable("clangDefaultBase", "prebuilts/clang/host")
+	pctx.VariableFunc("clangBase", func(config interface{}) (string, error) {
+		if override := config.(android.Config).Getenv("LLVM_PREBUILTS_BASE"); override != "" {
+			return override, nil
+		}
+		return "${clangDefaultBase}", nil
+	})
+	pctx.VariableFunc("clangVersion", func(config interface{}) (string, error) {
+		if override := config.(android.Config).Getenv("LLVM_PREBUILTS_VERSION"); override != "" {
+			return override, nil
+		}
+		return "clang-3016494", nil
+	})
+	pctx.StaticVariable("clangPath", "${clangBase}/${HostPrebuiltTag}/${clangVersion}")
+	pctx.StaticVariable("clangBin", "${clangPath}/bin")
+}
+
+var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+
+func bionicHeaders(bionicArch, kernelArch string) string {
+	return strings.Join([]string{
+		"-isystem bionic/libc/arch-" + bionicArch + "/include",
+		"-isystem bionic/libc/include",
+		"-isystem bionic/libc/kernel/uapi",
+		"-isystem bionic/libc/kernel/uapi/asm-" + kernelArch,
+		"-isystem bionic/libc/kernel/android/uapi",
+	}, " ")
+}
diff --git a/cc/installer.go b/cc/installer.go
new file mode 100644
index 0000000..7dc2b78
--- /dev/null
+++ b/cc/installer.go
@@ -0,0 +1,66 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"path/filepath"
+
+	"android/soong/android"
+)
+
+// This file handles installing files into their final location
+
+type InstallerProperties struct {
+	// install to a subdirectory of the default install path for the module
+	Relative_install_path string
+
+	// install symlinks to the module
+	Symlinks []string `android:"arch_variant"`
+}
+
+type baseInstaller struct {
+	Properties InstallerProperties
+
+	dir   string
+	dir64 string
+	data  bool
+
+	path android.OutputPath
+}
+
+var _ installer = (*baseInstaller)(nil)
+
+func (installer *baseInstaller) props() []interface{} {
+	return []interface{}{&installer.Properties}
+}
+
+func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
+	subDir := installer.dir
+	if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
+		subDir = installer.dir64
+	}
+	if !ctx.Host() && !ctx.Arch().Native {
+		subDir = filepath.Join(subDir, ctx.Arch().ArchType.String())
+	}
+	dir := android.PathForModuleInstall(ctx, subDir, installer.Properties.Relative_install_path)
+	installer.path = ctx.InstallFile(dir, file)
+	for _, symlink := range installer.Properties.Symlinks {
+		ctx.InstallSymlink(dir, symlink, installer.path)
+	}
+}
+
+func (installer *baseInstaller) inData() bool {
+	return installer.data
+}
diff --git a/cc/library.go b/cc/library.go
new file mode 100644
index 0000000..d92a267
--- /dev/null
+++ b/cc/library.go
@@ -0,0 +1,478 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"strings"
+
+	"github.com/google/blueprint"
+
+	"android/soong"
+	"android/soong/android"
+)
+
+type LibraryCompilerProperties struct {
+	Static struct {
+		Srcs         []string `android:"arch_variant"`
+		Exclude_srcs []string `android:"arch_variant"`
+		Cflags       []string `android:"arch_variant"`
+	} `android:"arch_variant"`
+	Shared struct {
+		Srcs         []string `android:"arch_variant"`
+		Exclude_srcs []string `android:"arch_variant"`
+		Cflags       []string `android:"arch_variant"`
+	} `android:"arch_variant"`
+}
+
+type FlagExporterProperties struct {
+	// list of directories relative to the Blueprints file that will
+	// be added to the include path using -I for any module that links against this module
+	Export_include_dirs []string `android:"arch_variant"`
+}
+
+type LibraryLinkerProperties struct {
+	Static struct {
+		Enabled           *bool    `android:"arch_variant"`
+		Whole_static_libs []string `android:"arch_variant"`
+		Static_libs       []string `android:"arch_variant"`
+		Shared_libs       []string `android:"arch_variant"`
+	} `android:"arch_variant"`
+	Shared struct {
+		Enabled           *bool    `android:"arch_variant"`
+		Whole_static_libs []string `android:"arch_variant"`
+		Static_libs       []string `android:"arch_variant"`
+		Shared_libs       []string `android:"arch_variant"`
+	} `android:"arch_variant"`
+
+	// local file name to pass to the linker as --version_script
+	Version_script *string `android:"arch_variant"`
+	// local file name to pass to the linker as -unexported_symbols_list
+	Unexported_symbols_list *string `android:"arch_variant"`
+	// local file name to pass to the linker as -force_symbols_not_weak_list
+	Force_symbols_not_weak_list *string `android:"arch_variant"`
+	// local file name to pass to the linker as -force_symbols_weak_list
+	Force_symbols_weak_list *string `android:"arch_variant"`
+
+	// rename host libraries to prevent overlap with system installed libraries
+	Unique_host_soname *bool
+
+	VariantName string `blueprint:"mutated"`
+}
+
+func init() {
+	soong.RegisterModuleType("cc_library_static", libraryStaticFactory)
+	soong.RegisterModuleType("cc_library_shared", librarySharedFactory)
+	soong.RegisterModuleType("cc_library", libraryFactory)
+	soong.RegisterModuleType("cc_library_host_static", libraryHostStaticFactory)
+	soong.RegisterModuleType("cc_library_host_shared", libraryHostSharedFactory)
+}
+
+// Module factory for combined static + shared libraries, device by default but with possible host
+// support
+func libraryFactory() (blueprint.Module, []interface{}) {
+	module := NewLibrary(android.HostAndDeviceSupported, true, true)
+	return module.Init()
+}
+
+// Module factory for static libraries
+func libraryStaticFactory() (blueprint.Module, []interface{}) {
+	module := NewLibrary(android.HostAndDeviceSupported, false, true)
+	return module.Init()
+}
+
+// Module factory for shared libraries
+func librarySharedFactory() (blueprint.Module, []interface{}) {
+	module := NewLibrary(android.HostAndDeviceSupported, true, false)
+	return module.Init()
+}
+
+// Module factory for host static libraries
+func libraryHostStaticFactory() (blueprint.Module, []interface{}) {
+	module := NewLibrary(android.HostSupported, false, true)
+	return module.Init()
+}
+
+// Module factory for host shared libraries
+func libraryHostSharedFactory() (blueprint.Module, []interface{}) {
+	module := NewLibrary(android.HostSupported, true, false)
+	return module.Init()
+}
+
+type flagExporter struct {
+	Properties FlagExporterProperties
+
+	flags []string
+}
+
+func (f *flagExporter) exportIncludes(ctx ModuleContext, inc string) {
+	includeDirs := android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
+	for _, dir := range includeDirs.Strings() {
+		f.flags = append(f.flags, inc+dir)
+	}
+}
+
+func (f *flagExporter) reexportFlags(flags []string) {
+	f.flags = append(f.flags, flags...)
+}
+
+func (f *flagExporter) exportedFlags() []string {
+	return f.flags
+}
+
+type exportedFlagsProducer interface {
+	exportedFlags() []string
+}
+
+var _ exportedFlagsProducer = (*flagExporter)(nil)
+
+type libraryCompiler struct {
+	baseCompiler
+
+	linker     *libraryLinker
+	Properties LibraryCompilerProperties
+
+	// For reusing static library objects for shared library
+	reuseObjFiles android.Paths
+}
+
+var _ compiler = (*libraryCompiler)(nil)
+
+func (library *libraryCompiler) props() []interface{} {
+	props := library.baseCompiler.props()
+	return append(props, &library.Properties)
+}
+
+func (library *libraryCompiler) flags(ctx ModuleContext, flags Flags) Flags {
+	flags = library.baseCompiler.flags(ctx, flags)
+
+	// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
+	// all code is position independent, and then those warnings get promoted to
+	// errors.
+	if ctx.Os() != android.Windows {
+		flags.CFlags = append(flags.CFlags, "-fPIC")
+	}
+
+	if library.linker.static() {
+		flags.CFlags = append(flags.CFlags, library.Properties.Static.Cflags...)
+	} else {
+		flags.CFlags = append(flags.CFlags, library.Properties.Shared.Cflags...)
+	}
+
+	return flags
+}
+
+func (library *libraryCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
+	var objFiles android.Paths
+
+	objFiles = library.baseCompiler.compile(ctx, flags, deps)
+	library.reuseObjFiles = objFiles
+
+	pathDeps := deps.GeneratedHeaders
+	pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
+
+	if library.linker.static() {
+		objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceStaticLibrary,
+			library.Properties.Static.Srcs, library.Properties.Static.Exclude_srcs,
+			nil, pathDeps)...)
+	} else {
+		objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceSharedLibrary,
+			library.Properties.Shared.Srcs, library.Properties.Shared.Exclude_srcs,
+			nil, pathDeps)...)
+	}
+
+	return objFiles
+}
+
+type libraryLinker struct {
+	baseLinker
+	flagExporter
+	stripper
+
+	Properties LibraryLinkerProperties
+
+	dynamicProperties struct {
+		BuildStatic bool `blueprint:"mutated"`
+		BuildShared bool `blueprint:"mutated"`
+	}
+
+	// If we're used as a whole_static_lib, our missing dependencies need
+	// to be given
+	wholeStaticMissingDeps []string
+
+	// For whole_static_libs
+	objFiles android.Paths
+
+	// Uses the module's name if empty, but can be overridden. Does not include
+	// shlib suffix.
+	libName string
+}
+
+var _ linker = (*libraryLinker)(nil)
+
+type libraryInterface interface {
+	getWholeStaticMissingDeps() []string
+	static() bool
+	objs() android.Paths
+}
+
+func (library *libraryLinker) props() []interface{} {
+	props := library.baseLinker.props()
+	return append(props,
+		&library.Properties,
+		&library.dynamicProperties,
+		&library.flagExporter.Properties,
+		&library.stripper.StripProperties)
+}
+
+func (library *libraryLinker) getLibName(ctx ModuleContext) string {
+	name := library.libName
+	if name == "" {
+		name = ctx.ModuleName()
+	}
+
+	if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
+		if !strings.HasSuffix(name, "-host") {
+			name = name + "-host"
+		}
+	}
+
+	return name + library.Properties.VariantName
+}
+
+func (library *libraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	flags = library.baseLinker.flags(ctx, flags)
+
+	if !library.static() {
+		libName := library.getLibName(ctx)
+		// GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
+		sharedFlag := "-Wl,-shared"
+		if flags.Clang || ctx.Host() {
+			sharedFlag = "-shared"
+		}
+		var f []string
+		if ctx.Device() {
+			f = append(f,
+				"-nostdlib",
+				"-Wl,--gc-sections",
+			)
+		}
+
+		if ctx.Darwin() {
+			f = append(f,
+				"-dynamiclib",
+				"-single_module",
+				//"-read_only_relocs suppress",
+				"-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(),
+			)
+		} else {
+			f = append(f,
+				sharedFlag,
+				"-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
+		}
+
+		flags.LdFlags = append(f, flags.LdFlags...)
+	}
+
+	return flags
+}
+
+func (library *libraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps = library.baseLinker.deps(ctx, deps)
+	if library.static() {
+		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Static.Whole_static_libs...)
+		deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
+		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
+	} else {
+		if ctx.Device() && !Bool(library.baseLinker.Properties.Nocrt) {
+			if !ctx.sdk() {
+				deps.CrtBegin = "crtbegin_so"
+				deps.CrtEnd = "crtend_so"
+			} else {
+				deps.CrtBegin = "ndk_crtbegin_so." + ctx.sdkVersion()
+				deps.CrtEnd = "ndk_crtend_so." + ctx.sdkVersion()
+			}
+		}
+		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
+		deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
+		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
+	}
+
+	return deps
+}
+
+func (library *libraryLinker) linkStatic(ctx ModuleContext,
+	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+	library.objFiles = append(android.Paths{}, deps.WholeStaticLibObjFiles...)
+	library.objFiles = append(library.objFiles, objFiles...)
+
+	outputFile := android.PathForModuleOut(ctx,
+		ctx.ModuleName()+library.Properties.VariantName+staticLibraryExtension)
+
+	if ctx.Darwin() {
+		TransformDarwinObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
+	} else {
+		TransformObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
+	}
+
+	library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
+
+	ctx.CheckbuildFile(outputFile)
+
+	return outputFile
+}
+
+func (library *libraryLinker) linkShared(ctx ModuleContext,
+	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+	var linkerDeps android.Paths
+
+	versionScript := android.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
+	unexportedSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Unexported_symbols_list)
+	forceNotWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_not_weak_list)
+	forceWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_weak_list)
+	if !ctx.Darwin() {
+		if versionScript.Valid() {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
+			linkerDeps = append(linkerDeps, versionScript.Path())
+		}
+		if unexportedSymbols.Valid() {
+			ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
+		}
+		if forceNotWeakSymbols.Valid() {
+			ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
+		}
+		if forceWeakSymbols.Valid() {
+			ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
+		}
+	} else {
+		if versionScript.Valid() {
+			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
+		}
+		if unexportedSymbols.Valid() {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
+			linkerDeps = append(linkerDeps, unexportedSymbols.Path())
+		}
+		if forceNotWeakSymbols.Valid() {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
+			linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
+		}
+		if forceWeakSymbols.Valid() {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
+			linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
+		}
+	}
+
+	fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
+	outputFile := android.PathForModuleOut(ctx, fileName)
+	ret := outputFile
+
+	builderFlags := flagsToBuilderFlags(flags)
+
+	if library.stripper.needsStrip(ctx) {
+		strippedOutputFile := outputFile
+		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
+		library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
+	}
+
+	sharedLibs := deps.SharedLibs
+	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
+
+	TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
+		deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
+		linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
+
+	return ret
+}
+
+func (library *libraryLinker) link(ctx ModuleContext,
+	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+	objFiles = append(objFiles, deps.ObjFiles...)
+
+	var out android.Path
+	if library.static() {
+		out = library.linkStatic(ctx, flags, deps, objFiles)
+	} else {
+		out = library.linkShared(ctx, flags, deps, objFiles)
+	}
+
+	library.exportIncludes(ctx, "-I")
+	library.reexportFlags(deps.ReexportedFlags)
+
+	return out
+}
+
+func (library *libraryLinker) buildStatic() bool {
+	return library.dynamicProperties.BuildStatic &&
+		(library.Properties.Static.Enabled == nil || *library.Properties.Static.Enabled)
+}
+
+func (library *libraryLinker) buildShared() bool {
+	return library.dynamicProperties.BuildShared &&
+		(library.Properties.Shared.Enabled == nil || *library.Properties.Shared.Enabled)
+}
+
+func (library *libraryLinker) getWholeStaticMissingDeps() []string {
+	return library.wholeStaticMissingDeps
+}
+
+func (library *libraryLinker) installable() bool {
+	return !library.static()
+}
+
+func (library *libraryLinker) objs() android.Paths {
+	return library.objFiles
+}
+
+type libraryInstaller struct {
+	baseInstaller
+
+	linker   *libraryLinker
+	sanitize *sanitize
+}
+
+func (library *libraryInstaller) install(ctx ModuleContext, file android.Path) {
+	if !library.linker.static() {
+		library.baseInstaller.install(ctx, file)
+	}
+}
+
+func (library *libraryInstaller) inData() bool {
+	return library.baseInstaller.inData() || library.sanitize.inData()
+}
+
+func NewLibrary(hod android.HostOrDeviceSupported, shared, static bool) *Module {
+	module := newModule(hod, android.MultilibBoth)
+
+	linker := &libraryLinker{}
+	linker.dynamicProperties.BuildShared = shared
+	linker.dynamicProperties.BuildStatic = static
+	module.linker = linker
+
+	module.compiler = &libraryCompiler{
+		linker: linker,
+	}
+	module.installer = &libraryInstaller{
+		baseInstaller: baseInstaller{
+			dir:   "lib",
+			dir64: "lib64",
+		},
+		linker:   linker,
+		sanitize: module.sanitize,
+	}
+
+	return module
+}
diff --git a/cc/linker.go b/cc/linker.go
new file mode 100644
index 0000000..c6f13f2
--- /dev/null
+++ b/cc/linker.go
@@ -0,0 +1,216 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+// This file contains the basic functionality for linking against static libraries and shared
+// libraries.  Final linking into libraries or executables is handled in library.go, binary.go, etc.
+
+type BaseLinkerProperties struct {
+	// list of modules whose object files should be linked into this module
+	// in their entirety.  For static library modules, all of the .o files from the intermediate
+	// directory of the dependency will be linked into this modules .a file.  For a shared library,
+	// the dependency's .a file will be linked into this module using -Wl,--whole-archive.
+	Whole_static_libs []string `android:"arch_variant,variant_prepend"`
+
+	// list of modules that should be statically linked into this module.
+	Static_libs []string `android:"arch_variant,variant_prepend"`
+
+	// list of modules that should be dynamically linked into this module.
+	Shared_libs []string `android:"arch_variant"`
+
+	// list of module-specific flags that will be used for all link steps
+	Ldflags []string `android:"arch_variant"`
+
+	// don't insert default compiler flags into asflags, cflags,
+	// cppflags, conlyflags, ldflags, or include_dirs
+	No_default_compiler_flags *bool
+
+	// list of system libraries that will be dynamically linked to
+	// shared library and executable modules.  If unset, generally defaults to libc
+	// and libm.  Set to [] to prevent linking against libc and libm.
+	System_shared_libs []string
+
+	// allow the module to contain undefined symbols.  By default,
+	// modules cannot contain undefined symbols that are not satisified by their immediate
+	// dependencies.  Set this flag to true to remove --no-undefined from the linker flags.
+	// This flag should only be necessary for compiling low-level libraries like libc.
+	Allow_undefined_symbols *bool
+
+	// don't link in libgcc.a
+	No_libgcc *bool
+
+	// -l arguments to pass to linker for host-provided shared libraries
+	Host_ldlibs []string `android:"arch_variant"`
+
+	// list of shared libraries to re-export include directories from. Entries must be
+	// present in shared_libs.
+	Export_shared_lib_headers []string `android:"arch_variant"`
+
+	// list of static libraries to re-export include directories from. Entries must be
+	// present in static_libs.
+	Export_static_lib_headers []string `android:"arch_variant"`
+
+	// don't link in crt_begin and crt_end.  This flag should only be necessary for
+	// compiling crt or libc.
+	Nocrt *bool `android:"arch_variant"`
+}
+
+// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
+type baseLinker struct {
+	Properties        BaseLinkerProperties
+	dynamicProperties struct {
+		VariantIsShared       bool     `blueprint:"mutated"`
+		VariantIsStatic       bool     `blueprint:"mutated"`
+		VariantIsStaticBinary bool     `blueprint:"mutated"`
+		RunPaths              []string `blueprint:"mutated"`
+	}
+}
+
+func (linker *baseLinker) appendLdflags(flags []string) {
+	linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
+}
+
+func (linker *baseLinker) begin(ctx BaseModuleContext) {
+	if ctx.toolchain().Is64Bit() {
+		linker.dynamicProperties.RunPaths = []string{"../lib64", "lib64"}
+	} else {
+		linker.dynamicProperties.RunPaths = []string{"../lib", "lib"}
+	}
+}
+
+func (linker *baseLinker) props() []interface{} {
+	return []interface{}{&linker.Properties, &linker.dynamicProperties}
+}
+
+func (linker *baseLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
+	deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
+	deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
+
+	deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...)
+	deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
+
+	if !ctx.sdk() && ctx.ModuleName() != "libcompiler_rt-extras" {
+		deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras")
+	}
+
+	if ctx.Device() {
+		// libgcc and libatomic have to be last on the command line
+		deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
+		if !Bool(linker.Properties.No_libgcc) {
+			deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
+		}
+
+		if !linker.static() {
+			if linker.Properties.System_shared_libs != nil {
+				deps.LateSharedLibs = append(deps.LateSharedLibs,
+					linker.Properties.System_shared_libs...)
+			} else if !ctx.sdk() {
+				deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm")
+			}
+		}
+
+		if ctx.sdk() {
+			deps.SharedLibs = append(deps.SharedLibs,
+				"libc",
+				"libm",
+			)
+		}
+	}
+
+	return deps
+}
+
+func (linker *baseLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	toolchain := ctx.toolchain()
+
+	flags.Nocrt = Bool(linker.Properties.Nocrt)
+
+	if !ctx.noDefaultCompilerFlags() {
+		if ctx.Device() && !Bool(linker.Properties.Allow_undefined_symbols) {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
+		}
+
+		if flags.Clang {
+			flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
+		} else {
+			flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
+		}
+
+		if ctx.Host() {
+			CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
+
+			flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...)
+		}
+	}
+
+	CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
+
+	flags.LdFlags = append(flags.LdFlags, linker.Properties.Ldflags...)
+
+	if ctx.Host() && !linker.static() {
+		rpath_prefix := `\$$ORIGIN/`
+		if ctx.Darwin() {
+			rpath_prefix = "@loader_path/"
+		}
+
+		for _, rpath := range linker.dynamicProperties.RunPaths {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
+		}
+	}
+
+	if flags.Clang {
+		flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
+	} else {
+		flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
+	}
+
+	return flags
+}
+
+func (linker *baseLinker) static() bool {
+	return linker.dynamicProperties.VariantIsStatic
+}
+
+func (linker *baseLinker) staticBinary() bool {
+	return linker.dynamicProperties.VariantIsStaticBinary
+}
+
+func (linker *baseLinker) setStatic(static bool) {
+	linker.dynamicProperties.VariantIsStatic = static
+}
+
+func (linker *baseLinker) isDependencyRoot() bool {
+	return false
+}
+
+type baseLinkerInterface interface {
+	// Returns true if the build options for the module have selected a static or shared build
+	buildStatic() bool
+	buildShared() bool
+
+	// Sets whether a specific variant is static or shared
+	setStatic(bool)
+
+	// Returns whether a specific variant is a static library or binary
+	static() bool
+
+	// Returns whether a module is a static binary
+	staticBinary() bool
+
+	// Returns true for dependency roots (binaries)
+	// TODO(ccross): also handle dlopenable libraries
+	isDependencyRoot() bool
+}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 562186e..50db938 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -35,6 +35,30 @@
 		}, "arch", "apiLevel")
 
 	ndkLibrarySuffix = ".ndk"
+
+	ndkPrebuiltSharedLibs = []string{
+		"android",
+		"c",
+		"dl",
+		"EGL",
+		"GLESv1_CM",
+		"GLESv2",
+		"GLESv3",
+		"jnigraphics",
+		"log",
+		"mediandk",
+		"m",
+		"OpenMAXAL",
+		"OpenSLES",
+		"stdc++",
+		"vulkan",
+		"z",
+	}
+	ndkPrebuiltSharedLibraries = addPrefix(append([]string(nil), ndkPrebuiltSharedLibs...), "lib")
+
+	// These libraries have migrated over to the new ndk_library, which is added
+	// as a variation dependency via depsMutator.
+	ndkMigratedLibs = []string{}
 )
 
 // Creates a stub shared library based on the provided version file.
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
new file mode 100644
index 0000000..f66f5b5
--- /dev/null
+++ b/cc/ndk_prebuilt.go
@@ -0,0 +1,224 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/google/blueprint"
+
+	"android/soong"
+	"android/soong/android"
+)
+
+func init() {
+	soong.RegisterModuleType("ndk_prebuilt_library", ndkPrebuiltLibraryFactory)
+	soong.RegisterModuleType("ndk_prebuilt_object", ndkPrebuiltObjectFactory)
+	soong.RegisterModuleType("ndk_prebuilt_static_stl", ndkPrebuiltStaticStlFactory)
+	soong.RegisterModuleType("ndk_prebuilt_shared_stl", ndkPrebuiltSharedStlFactory)
+}
+
+// NDK prebuilt libraries.
+//
+// These differ from regular prebuilts in that they aren't stripped and usually aren't installed
+// either (with the exception of the shared STLs, which are installed to the app's directory rather
+// than to the system image).
+
+func getNdkLibDir(ctx android.ModuleContext, toolchain Toolchain, version string) android.SourcePath {
+	suffix := ""
+	// Most 64-bit NDK prebuilts store libraries in "lib64", except for arm64 which is not a
+	// multilib toolchain and stores the libraries in "lib".
+	if toolchain.Is64Bit() && ctx.Arch().ArchType != android.Arm64 {
+		suffix = "64"
+	}
+	return android.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib%s",
+		version, toolchain.Name(), suffix))
+}
+
+func ndkPrebuiltModuleToPath(ctx android.ModuleContext, toolchain Toolchain,
+	ext string, version string) android.Path {
+
+	// NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
+	// We want to translate to just NAME.EXT
+	name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
+	dir := getNdkLibDir(ctx, toolchain, version)
+	return dir.Join(ctx, name+ext)
+}
+
+type ndkPrebuiltObjectLinker struct {
+	objectLinker
+}
+
+func (*ndkPrebuiltObjectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	// NDK objects can't have any dependencies
+	return deps
+}
+
+func ndkPrebuiltObjectFactory() (blueprint.Module, []interface{}) {
+	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+	module.linker = &ndkPrebuiltObjectLinker{}
+	module.Properties.HideFromMake = true
+	return module.Init()
+}
+
+func (c *ndkPrebuiltObjectLinker) link(ctx ModuleContext, flags Flags,
+	deps PathDeps, objFiles android.Paths) android.Path {
+	// A null build step, but it sets up the output path.
+	if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
+		ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name")
+	}
+
+	return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion())
+}
+
+type ndkPrebuiltLibraryLinker struct {
+	libraryLinker
+}
+
+var _ baseLinkerInterface = (*ndkPrebuiltLibraryLinker)(nil)
+var _ exportedFlagsProducer = (*libraryLinker)(nil)
+
+func (ndk *ndkPrebuiltLibraryLinker) props() []interface{} {
+	return append(ndk.libraryLinker.props(), &ndk.Properties, &ndk.flagExporter.Properties)
+}
+
+func (*ndkPrebuiltLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	// NDK libraries can't have any dependencies
+	return deps
+}
+
+func ndkPrebuiltLibraryFactory() (blueprint.Module, []interface{}) {
+	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+	linker := &ndkPrebuiltLibraryLinker{}
+	linker.dynamicProperties.BuildShared = true
+	module.linker = linker
+	module.Properties.HideFromMake = true
+	return module.Init()
+}
+
+func (ndk *ndkPrebuiltLibraryLinker) link(ctx ModuleContext, flags Flags,
+	deps PathDeps, objFiles android.Paths) android.Path {
+	// A null build step, but it sets up the output path.
+	ndk.exportIncludes(ctx, "-isystem")
+
+	return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),
+		ctx.sdkVersion())
+}
+
+// The NDK STLs are slightly different from the prebuilt system libraries:
+//     * Are not specific to each platform version.
+//     * The libraries are not in a predictable location for each STL.
+
+type ndkPrebuiltStlLinker struct {
+	ndkPrebuiltLibraryLinker
+}
+
+func ndkPrebuiltSharedStlFactory() (blueprint.Module, []interface{}) {
+	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+	linker := &ndkPrebuiltStlLinker{}
+	linker.dynamicProperties.BuildShared = true
+	module.linker = linker
+	module.Properties.HideFromMake = true
+	return module.Init()
+}
+
+func ndkPrebuiltStaticStlFactory() (blueprint.Module, []interface{}) {
+	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+	linker := &ndkPrebuiltStlLinker{}
+	linker.dynamicProperties.BuildStatic = true
+	module.linker = linker
+	module.Properties.HideFromMake = true
+	return module.Init()
+}
+
+func getNdkStlLibDir(ctx android.ModuleContext, toolchain Toolchain, stl string) android.SourcePath {
+	gccVersion := toolchain.GccVersion()
+	var libDir string
+	switch stl {
+	case "libstlport":
+		libDir = "cxx-stl/stlport/libs"
+	case "libc++":
+		libDir = "cxx-stl/llvm-libc++/libs"
+	case "libgnustl":
+		libDir = fmt.Sprintf("cxx-stl/gnu-libstdc++/%s/libs", gccVersion)
+	}
+
+	if libDir != "" {
+		ndkSrcRoot := "prebuilts/ndk/current/sources"
+		return android.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0])
+	}
+
+	ctx.ModuleErrorf("Unknown NDK STL: %s", stl)
+	return android.PathForSource(ctx, "")
+}
+
+func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
+	deps PathDeps, objFiles android.Paths) android.Path {
+	// A null build step, but it sets up the output path.
+	if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
+		ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
+	}
+
+	ndk.exportIncludes(ctx, "-I")
+
+	libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
+	libExt := flags.Toolchain.ShlibSuffix()
+	if ndk.dynamicProperties.BuildStatic {
+		libExt = staticLibraryExtension
+	}
+
+	stlName := strings.TrimSuffix(libName, "_shared")
+	stlName = strings.TrimSuffix(stlName, "_static")
+	libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName)
+	return libDir.Join(ctx, libName+libExt)
+}
+
+func linkageMutator(mctx android.BottomUpMutatorContext) {
+	if m, ok := mctx.Module().(*Module); ok {
+		if m.linker != nil {
+			if linker, ok := m.linker.(baseLinkerInterface); ok {
+				var modules []blueprint.Module
+				if linker.buildStatic() && linker.buildShared() {
+					modules = mctx.CreateLocalVariations("static", "shared")
+					static := modules[0].(*Module)
+					shared := modules[1].(*Module)
+
+					static.linker.(baseLinkerInterface).setStatic(true)
+					shared.linker.(baseLinkerInterface).setStatic(false)
+
+					if staticCompiler, ok := static.compiler.(*libraryCompiler); ok {
+						sharedCompiler := shared.compiler.(*libraryCompiler)
+						if len(staticCompiler.Properties.Static.Cflags) == 0 &&
+							len(sharedCompiler.Properties.Shared.Cflags) == 0 {
+							// Optimize out compiling common .o files twice for static+shared libraries
+							mctx.AddInterVariantDependency(reuseObjTag, shared, static)
+							sharedCompiler.baseCompiler.Properties.Srcs = nil
+							sharedCompiler.baseCompiler.Properties.Generated_sources = nil
+						}
+					}
+				} else if linker.buildStatic() {
+					modules = mctx.CreateLocalVariations("static")
+					modules[0].(*Module).linker.(baseLinkerInterface).setStatic(true)
+				} else if linker.buildShared() {
+					modules = mctx.CreateLocalVariations("shared")
+					modules[0].(*Module).linker.(baseLinkerInterface).setStatic(false)
+				} else {
+					panic(fmt.Errorf("library %q not static or shared", mctx.ModuleName()))
+				}
+			}
+		}
+	}
+}
diff --git a/cc/object.go b/cc/object.go
new file mode 100644
index 0000000..456e1bb
--- /dev/null
+++ b/cc/object.go
@@ -0,0 +1,90 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"fmt"
+
+	"github.com/google/blueprint"
+
+	"android/soong"
+	"android/soong/android"
+)
+
+//
+// Objects (for crt*.o)
+//
+
+func init() {
+	soong.RegisterModuleType("cc_object", objectFactory)
+}
+
+type objectLinker struct {
+	Properties ObjectLinkerProperties
+}
+
+func objectFactory() (blueprint.Module, []interface{}) {
+	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+	module.compiler = &baseCompiler{}
+	module.linker = &objectLinker{}
+	return module.Init()
+}
+
+func (object *objectLinker) appendLdflags(flags []string) {
+	panic(fmt.Errorf("appendLdflags on object Linker not supported"))
+}
+
+func (object *objectLinker) props() []interface{} {
+	return []interface{}{&object.Properties}
+}
+
+func (*objectLinker) begin(ctx BaseModuleContext) {}
+
+func (object *objectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
+	return deps
+}
+
+func (*objectLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	if flags.Clang {
+		flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
+	} else {
+		flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainLdflags())
+	}
+
+	return flags
+}
+
+func (object *objectLinker) link(ctx ModuleContext,
+	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+	objFiles = append(objFiles, deps.ObjFiles...)
+
+	var outputFile android.Path
+	if len(objFiles) == 1 {
+		outputFile = objFiles[0]
+	} else {
+		output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
+		TransformObjsToObj(ctx, objFiles, flagsToBuilderFlags(flags), output)
+		outputFile = output
+	}
+
+	ctx.CheckbuildFile(outputFile)
+	return outputFile
+}
+
+func (*objectLinker) installable() bool {
+	return false
+}
diff --git a/cc/strip.go b/cc/strip.go
new file mode 100644
index 0000000..bc16bbc
--- /dev/null
+++ b/cc/strip.go
@@ -0,0 +1,44 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import "android/soong/android"
+
+type StripProperties struct {
+	Strip struct {
+		None         bool
+		Keep_symbols bool
+	}
+}
+
+type stripper struct {
+	StripProperties StripProperties
+}
+
+func (stripper *stripper) needsStrip(ctx ModuleContext) bool {
+	return !ctx.AConfig().EmbeddedInMake() && !stripper.StripProperties.Strip.None
+}
+
+func (stripper *stripper) strip(ctx ModuleContext, in, out android.ModuleOutPath,
+	flags builderFlags) {
+	if ctx.Darwin() {
+		TransformDarwinStrip(ctx, in, out)
+	} else {
+		flags.stripKeepSymbols = stripper.StripProperties.Strip.Keep_symbols
+		// TODO(ccross): don't add gnu debuglink for user builds
+		flags.stripAddGnuDebuglink = true
+		TransformStrip(ctx, in, out, flags)
+	}
+}
diff --git a/cc/test.go b/cc/test.go
new file mode 100644
index 0000000..9eb4e21
--- /dev/null
+++ b/cc/test.go
@@ -0,0 +1,256 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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.
+
+package cc
+
+import (
+	"path/filepath"
+	"strings"
+
+	"github.com/google/blueprint"
+
+	"android/soong"
+	"android/soong/android"
+)
+
+type TestLinkerProperties struct {
+	// if set, build against the gtest library. Defaults to true.
+	Gtest bool
+
+	// Create a separate binary for each source file.  Useful when there is
+	// global state that can not be torn down and reset between each test suite.
+	Test_per_src *bool
+}
+
+func init() {
+	soong.RegisterModuleType("cc_test", testFactory)
+	soong.RegisterModuleType("cc_test_library", testLibraryFactory)
+	soong.RegisterModuleType("cc_benchmark", benchmarkFactory)
+	soong.RegisterModuleType("cc_test_host", testHostFactory)
+	soong.RegisterModuleType("cc_benchmark_host", benchmarkHostFactory)
+}
+
+// Module factory for tests
+func testFactory() (blueprint.Module, []interface{}) {
+	module := NewTest(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+// Module factory for test libraries
+func testLibraryFactory() (blueprint.Module, []interface{}) {
+	module := NewTestLibrary(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+// Module factory for benchmarks
+func benchmarkFactory() (blueprint.Module, []interface{}) {
+	module := NewBenchmark(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+// Module factory for host tests
+func testHostFactory() (blueprint.Module, []interface{}) {
+	module := NewTest(android.HostSupported)
+	return module.Init()
+}
+
+// Module factory for host benchmarks
+func benchmarkHostFactory() (blueprint.Module, []interface{}) {
+	module := NewBenchmark(android.HostSupported)
+	return module.Init()
+}
+
+func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
+	if m, ok := mctx.Module().(*Module); ok {
+		if test, ok := m.linker.(*testBinaryLinker); ok {
+			if Bool(test.testLinker.Properties.Test_per_src) {
+				testNames := make([]string, len(m.compiler.(*baseCompiler).Properties.Srcs))
+				for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
+					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
+				}
+				tests := mctx.CreateLocalVariations(testNames...)
+				for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
+					tests[i].(*Module).compiler.(*baseCompiler).Properties.Srcs = []string{src}
+					tests[i].(*Module).linker.(*testBinaryLinker).binaryLinker.Properties.Stem = testNames[i]
+				}
+			}
+		}
+	}
+}
+
+type testLinker struct {
+	Properties TestLinkerProperties
+}
+
+func (test *testLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	if !test.Properties.Gtest {
+		return flags
+	}
+
+	flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING")
+	if ctx.Host() {
+		flags.CFlags = append(flags.CFlags, "-O0", "-g")
+
+		switch ctx.Os() {
+		case android.Windows:
+			flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS")
+		case android.Linux:
+			flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX")
+			flags.LdFlags = append(flags.LdFlags, "-lpthread")
+		case android.Darwin:
+			flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC")
+			flags.LdFlags = append(flags.LdFlags, "-lpthread")
+		}
+	} else {
+		flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID")
+	}
+
+	return flags
+}
+
+func (test *testLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	if test.Properties.Gtest {
+		if ctx.sdk() && ctx.Device() {
+			switch ctx.selectedStl() {
+			case "ndk_libc++_shared", "ndk_libc++_static":
+				deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
+			case "ndk_libgnustl_static":
+				deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_gnustl", "libgtest_ndk_gnustl")
+			default:
+				deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk", "libgtest_ndk")
+			}
+		} else {
+			deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
+		}
+	}
+	return deps
+}
+
+type testBinaryLinker struct {
+	testLinker
+	binaryLinker
+}
+
+func (test *testBinaryLinker) begin(ctx BaseModuleContext) {
+	test.binaryLinker.begin(ctx)
+	runpath := "../../lib"
+	if ctx.toolchain().Is64Bit() {
+		runpath += "64"
+	}
+	test.dynamicProperties.RunPaths = append([]string{runpath}, test.dynamicProperties.RunPaths...)
+}
+
+func (test *testBinaryLinker) props() []interface{} {
+	return append(test.binaryLinker.props(), &test.testLinker.Properties)
+}
+
+func (test *testBinaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	flags = test.binaryLinker.flags(ctx, flags)
+	flags = test.testLinker.flags(ctx, flags)
+	return flags
+}
+
+func (test *testBinaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps = test.testLinker.deps(ctx, deps)
+	deps = test.binaryLinker.deps(ctx, deps)
+	return deps
+}
+
+type testLibraryLinker struct {
+	testLinker
+	*libraryLinker
+}
+
+func (test *testLibraryLinker) props() []interface{} {
+	return append(test.libraryLinker.props(), &test.testLinker.Properties)
+}
+
+func (test *testLibraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	flags = test.libraryLinker.flags(ctx, flags)
+	flags = test.testLinker.flags(ctx, flags)
+	return flags
+}
+
+func (test *testLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps = test.testLinker.deps(ctx, deps)
+	deps = test.libraryLinker.deps(ctx, deps)
+	return deps
+}
+
+type testInstaller struct {
+	baseInstaller
+}
+
+func (installer *testInstaller) install(ctx ModuleContext, file android.Path) {
+	installer.dir = filepath.Join(installer.dir, ctx.ModuleName())
+	installer.dir64 = filepath.Join(installer.dir64, ctx.ModuleName())
+	installer.baseInstaller.install(ctx, file)
+}
+
+func NewTest(hod android.HostOrDeviceSupported) *Module {
+	module := newModule(hod, android.MultilibBoth)
+	module.compiler = &baseCompiler{}
+	linker := &testBinaryLinker{}
+	linker.testLinker.Properties.Gtest = true
+	module.linker = linker
+	module.installer = &testInstaller{
+		baseInstaller: baseInstaller{
+			dir:   "nativetest",
+			dir64: "nativetest64",
+			data:  true,
+		},
+	}
+	return module
+}
+
+func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
+	module := NewLibrary(android.HostAndDeviceSupported, false, true)
+	linker := &testLibraryLinker{
+		libraryLinker: module.linker.(*libraryLinker),
+	}
+	linker.testLinker.Properties.Gtest = true
+	module.linker = linker
+	module.installer = &testInstaller{
+		baseInstaller: baseInstaller{
+			dir:   "nativetest",
+			dir64: "nativetest64",
+			data:  true,
+		},
+	}
+	return module
+}
+
+type benchmarkLinker struct {
+	testBinaryLinker
+}
+
+func (benchmark *benchmarkLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps = benchmark.testBinaryLinker.deps(ctx, deps)
+	deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
+	return deps
+}
+
+func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
+	module := newModule(hod, android.MultilibFirst)
+	module.compiler = &baseCompiler{}
+	module.linker = &benchmarkLinker{}
+	module.installer = &testInstaller{
+		baseInstaller: baseInstaller{
+			dir:   "nativetest",
+			dir64: "nativetest64",
+			data:  true,
+		},
+	}
+	return module
+}
diff --git a/cc/toolchain.go b/cc/toolchain.go
index 0cb7c9c..2e2ee5a 100644
--- a/cc/toolchain.go
+++ b/cc/toolchain.go
@@ -16,7 +16,6 @@
 
 import (
 	"fmt"
-	"strings"
 
 	"android/soong/android"
 )
@@ -140,13 +139,3 @@
 func (toolchain32Bit) Is64Bit() bool {
 	return false
 }
-
-func bionicHeaders(bionicArch, kernelArch string) string {
-	return strings.Join([]string{
-		"-isystem bionic/libc/arch-" + bionicArch + "/include",
-		"-isystem bionic/libc/include",
-		"-isystem bionic/libc/kernel/uapi",
-		"-isystem bionic/libc/kernel/uapi/asm-" + kernelArch,
-		"-isystem bionic/libc/kernel/android/uapi",
-	}, " ")
-}