Initial prebuilt support

Support prebuilt shared libraries as an initial proof-of-concept of
prebuilts.  Future changes will support binaries and static libraries,
and the ability to select which to use based on something besides
blueprint properties.

Test: TestPrebuilts run during m -j
Change-Id: I6e84da667e9005ae11844bad01d25cbe4ced1ce3
diff --git a/Android.bp b/Android.bp
index 0ba669c..8821098 100644
--- a/Android.bp
+++ b/Android.bp
@@ -72,6 +72,7 @@
         "android/onceper.go",
         "android/package_ctx.go",
         "android/paths.go",
+        "android/prebuilt.go",
         "android/register.go",
         "android/util.go",
         "android/variable.go",
@@ -81,6 +82,7 @@
     ],
     testSrcs: [
         "android/paths_test.go",
+        "android/prebuilt_test.go",
     ],
 }
 
@@ -126,6 +128,7 @@
         "cc/check.go",
         "cc/gen.go",
         "cc/makevars.go",
+        "cc/prebuilt.go",
         "cc/relocation_packer.go",
         "cc/sanitize.go",
         "cc/stl.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 28c2290..469ac7f 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -34,6 +34,7 @@
 
 type AndroidMkDataProvider interface {
 	AndroidMk() (AndroidMkData, error)
+	BaseModuleName() string
 }
 
 type AndroidMkData struct {
@@ -142,13 +143,12 @@
 }
 
 func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod blueprint.Module) error {
-	name := ctx.ModuleName(mod)
-
 	provider, ok := mod.(AndroidMkDataProvider)
 	if !ok {
 		return nil
 	}
 
+	name := provider.BaseModuleName()
 	amod := mod.(Module).base()
 	data, err := provider.AndroidMk()
 	if err != nil {
@@ -156,7 +156,11 @@
 	}
 
 	if !amod.Enabled() {
-		return err
+		return nil
+	}
+
+	if amod.commonProperties.SkipInstall {
+		return nil
 	}
 
 	if data.SubName != "" {
diff --git a/android/config.go b/android/config.go
index b29012c..1d3fba2 100644
--- a/android/config.go
+++ b/android/config.go
@@ -151,6 +151,11 @@
 	return nil
 }
 
+// TestConfig returns a Config object suitable for using for tests
+func TestConfig() Config {
+	return Config{&config{}}
+}
+
 // New creates a new Config object.  The srcDir argument specifies the path to
 // the root source directory. It also loads the config file, if found.
 func NewConfig(srcDir, buildDir string) (Config, error) {
diff --git a/android/module.go b/android/module.go
index 52280d2..572b162 100644
--- a/android/module.go
+++ b/android/module.go
@@ -147,6 +147,8 @@
 	// Set by InitAndroidModule
 	HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
 	ArchSpecific          bool                  `blueprint:"mutated"`
+
+	SkipInstall bool `blueprint:"mutated"`
 }
 
 type hostAndDeviceProperties struct {
@@ -277,10 +279,17 @@
 	hooks hooks
 }
 
+// Name returns the name of the module.  It may be overridden by individual module types, for
+// example prebuilts will prepend prebuilt_ to the name.
 func (a *ModuleBase) Name() string {
 	return a.nameProperties.Name
 }
 
+// BaseModuleName returns the name of the module as specified in the blueprints file.
+func (a *ModuleBase) BaseModuleName() string {
+	return a.nameProperties.Name
+}
+
 func (a *ModuleBase) base() *ModuleBase {
 	return a
 }
@@ -348,6 +357,10 @@
 	return *a.commonProperties.Enabled
 }
 
+func (a *ModuleBase) SkipInstall() {
+	a.commonProperties.SkipInstall = true
+}
+
 func (a *ModuleBase) computeInstallDeps(
 	ctx blueprint.ModuleContext) Paths {
 
@@ -600,7 +613,9 @@
 	fullInstallPath := installPath.Join(a, name)
 	a.module.base().hooks.runInstallHooks(a, fullInstallPath, false)
 
-	if a.Host() || !a.AConfig().SkipDeviceInstall() {
+	if !a.module.base().commonProperties.SkipInstall &&
+		(a.Host() || !a.AConfig().SkipDeviceInstall()) {
+
 		deps = append(deps, a.installDeps...)
 
 		var implicitDeps, orderOnlyDeps Paths
@@ -636,7 +651,9 @@
 	fullInstallPath := installPath.Join(a, name)
 	a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
 
-	if a.Host() || !a.AConfig().SkipDeviceInstall() {
+	if !a.module.base().commonProperties.SkipInstall &&
+		(a.Host() || !a.AConfig().SkipDeviceInstall()) {
+
 		a.ModuleBuild(pctx, ModuleBuildParams{
 			Rule:      Symlink,
 			Output:    fullInstallPath,
diff --git a/android/mutator.go b/android/mutator.go
index b375bce..8114b3e 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -33,6 +33,7 @@
 	}
 
 	ctx.TopDown("load_hooks", loadHookMutator).Parallel()
+	ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
 	ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
 	ctx.TopDown("defaults", defaultsMutator).Parallel()
 
@@ -45,6 +46,9 @@
 
 	ctx.BottomUp("deps", depsMutator).Parallel()
 
+	ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
+	ctx.TopDown("prebuilt_disable", PrebuiltDisableMutator).Parallel()
+
 	register(postDeps)
 }
 
diff --git a/android/prebuilt.go b/android/prebuilt.go
new file mode 100644
index 0000000..fb9e515
--- /dev/null
+++ b/android/prebuilt.go
@@ -0,0 +1,121 @@
+// 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 android
+
+import "github.com/google/blueprint"
+
+// This file implements common functionality for handling modules that may exist as prebuilts,
+// source, or both.
+
+var prebuiltDependencyTag blueprint.BaseDependencyTag
+
+func SourceModuleHasPrebuilt(ctx ModuleContext) OptionalPath {
+	var path Path
+	ctx.VisitDirectDeps(func(m blueprint.Module) {
+		if ctx.OtherModuleDependencyTag(m) == prebuiltDependencyTag {
+			p := m.(PrebuiltInterface).Prebuilt()
+			if p.usePrebuilt(ctx) {
+				path = p.Path(ctx)
+			}
+		}
+	})
+
+	return OptionalPathForPath(path)
+}
+
+type Prebuilt struct {
+	Properties struct {
+		Srcs []string `android:"arch_variant"`
+		// When prefer is set to true the prebuilt will be used instead of any source module with
+		// a matching name.
+		Prefer bool `android:"arch_variant"`
+
+		SourceExists bool `blueprint:"mutated"`
+	}
+	module Module
+}
+
+func (p *Prebuilt) Name(name string) string {
+	return "prebuilt_" + name
+}
+
+func (p *Prebuilt) Path(ctx ModuleContext) Path {
+	if len(p.Properties.Srcs) == 0 {
+		ctx.PropertyErrorf("srcs", "missing prebuilt source file")
+		return nil
+	}
+
+	if len(p.Properties.Srcs) > 1 {
+		ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
+		return nil
+	}
+
+	return PathForModuleSrc(ctx, p.Properties.Srcs[0])
+}
+
+type PrebuiltInterface interface {
+	Module
+	Prebuilt() *Prebuilt
+}
+
+type PrebuiltSourceInterface interface {
+	SkipInstall()
+}
+
+// prebuiltMutator ensures that there is always a module with an undecorated name, and marks
+// prebuilt modules that have both a prebuilt and a source module.
+func prebuiltMutator(ctx BottomUpMutatorContext) {
+	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
+		p := m.Prebuilt()
+		name := m.base().BaseModuleName()
+		if ctx.OtherModuleExists(name) {
+			ctx.AddReverseDependency(ctx.Module(), prebuiltDependencyTag, name)
+			p.Properties.SourceExists = true
+		} else {
+			ctx.Rename(name)
+		}
+	}
+}
+
+// PrebuiltReplaceMutator replaces dependencies on the source module with dependencies on the prebuilt
+// when both modules exist and the prebuilt should be used.
+func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) {
+	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
+		p := m.Prebuilt()
+		name := m.base().BaseModuleName()
+		if p.Properties.SourceExists && p.usePrebuilt(ctx) {
+			ctx.ReplaceDependencies(name)
+		}
+	}
+}
+
+// PrebuiltDisableMutator disables source modules that have prebuilts that should be used instead.
+func PrebuiltDisableMutator(ctx TopDownMutatorContext) {
+	if s, ok := ctx.Module().(PrebuiltSourceInterface); ok {
+		ctx.VisitDirectDeps(func(m blueprint.Module) {
+			if ctx.OtherModuleDependencyTag(m) == prebuiltDependencyTag {
+				p := m.(PrebuiltInterface).Prebuilt()
+				if p.usePrebuilt(ctx) {
+					s.SkipInstall()
+				}
+			}
+		})
+	}
+}
+
+func (p *Prebuilt) usePrebuilt(ctx BaseContext) bool {
+	// TODO: use p.Properties.Name and ctx.ModuleDir to override prefer
+	return p.Properties.Prefer && len(p.Properties.Srcs) > 0
+}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
new file mode 100644
index 0000000..92d6481
--- /dev/null
+++ b/android/prebuilt_test.go
@@ -0,0 +1,206 @@
+// 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 android
+
+import (
+	"testing"
+
+	"github.com/google/blueprint"
+)
+
+var prebuiltsTests = []struct {
+	name     string
+	modules  string
+	prebuilt bool
+}{
+	{
+		name: "no prebuilt",
+		modules: `
+			source {
+				name: "bar",
+			}`,
+		prebuilt: false,
+	},
+	{
+		name: "no source prebuilt not preferred",
+		modules: `
+			prebuilt {
+				name: "bar",
+				prefer: false,
+				srcs: ["prebuilt"],
+			}`,
+		prebuilt: true,
+	},
+	{
+		name: "no source prebuilt preferred",
+		modules: `
+			prebuilt {
+				name: "bar",
+				prefer: true,
+				srcs: ["prebuilt"],
+			}`,
+		prebuilt: true,
+	},
+	{
+		name: "prebuilt not preferred",
+		modules: `
+			source {
+				name: "bar",
+			}
+			
+			prebuilt {
+				name: "bar",
+				prefer: false,
+				srcs: ["prebuilt"],
+			}`,
+		prebuilt: false,
+	},
+	{
+		name: "prebuilt preferred",
+		modules: `
+			source {
+				name: "bar",
+			}
+			
+			prebuilt {
+				name: "bar",
+				prefer: true,
+				srcs: ["prebuilt"],
+			}`,
+		prebuilt: true,
+	},
+}
+
+func TestPrebuilts(t *testing.T) {
+	for _, test := range prebuiltsTests {
+		t.Run(test.name, func(t *testing.T) {
+			ctx := NewContext()
+			ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
+			ctx.RegisterModuleType("source", newSourceModule)
+			ctx.MockFileSystem(map[string][]byte{
+				"Blueprints": []byte(`
+					source {
+						name: "foo",
+						deps: ["bar"],
+					}
+					` + test.modules),
+			})
+
+			config := TestConfig()
+
+			_, errs := ctx.ParseBlueprintsFiles("Blueprints")
+			fail(t, errs)
+			_, errs = ctx.PrepareBuildActions(config)
+			fail(t, errs)
+
+			foo := findModule(ctx, "foo")
+			if foo == nil {
+				t.Fatalf("failed to find module foo")
+			}
+
+			if test.prebuilt {
+				if !foo.(*sourceModule).dependsOnPrebuiltModule {
+					t.Errorf("doesn't depend on prebuilt module")
+				}
+
+				if foo.(*sourceModule).dependsOnSourceModule {
+					t.Errorf("depends on source module")
+				}
+			} else {
+				if foo.(*sourceModule).dependsOnPrebuiltModule {
+					t.Errorf("depends on prebuilt module")
+				}
+
+				if !foo.(*sourceModule).dependsOnSourceModule {
+					t.Errorf("doens't depend on source module")
+				}
+			}
+		})
+	}
+
+}
+
+type prebuiltModule struct {
+	ModuleBase
+	prebuilt Prebuilt
+}
+
+func newPrebuiltModule() (blueprint.Module, []interface{}) {
+	m := &prebuiltModule{}
+	return InitAndroidModule(m, &m.prebuilt.Properties)
+}
+
+func (p *prebuiltModule) Name() string {
+	return p.prebuilt.Name(p.ModuleBase.Name())
+}
+
+func (p *prebuiltModule) DepsMutator(ctx BottomUpMutatorContext) {
+}
+
+func (p *prebuiltModule) GenerateAndroidBuildActions(ModuleContext) {
+}
+
+func (p *prebuiltModule) Prebuilt() *Prebuilt {
+	return &p.prebuilt
+}
+
+type sourceModule struct {
+	ModuleBase
+	properties struct {
+		Deps []string
+	}
+	dependsOnSourceModule, dependsOnPrebuiltModule bool
+}
+
+func newSourceModule() (blueprint.Module, []interface{}) {
+	m := &sourceModule{}
+	return InitAndroidModule(m, &m.properties)
+}
+
+func (s *sourceModule) DepsMutator(ctx BottomUpMutatorContext) {
+	for _, d := range s.properties.Deps {
+		ctx.AddDependency(ctx.Module(), nil, d)
+	}
+}
+
+func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	ctx.VisitDirectDeps(func(m blueprint.Module) {
+		if _, ok := m.(*sourceModule); ok {
+			s.dependsOnSourceModule = true
+		}
+		if _, ok := m.(*prebuiltModule); ok {
+			s.dependsOnPrebuiltModule = true
+		}
+	})
+}
+
+func findModule(ctx *blueprint.Context, name string) blueprint.Module {
+	var ret blueprint.Module
+	ctx.VisitAllModules(func(m blueprint.Module) {
+		if ctx.ModuleName(m) == name {
+			ret = m
+		}
+	})
+	return ret
+}
+
+func fail(t *testing.T, errs []error) {
+	if len(errs) > 0 {
+		for _, err := range errs {
+			t.Error(err)
+		}
+		t.FailNow()
+	}
+}
diff --git a/cc/binary.go b/cc/binary.go
index 0965886..e7d22c1 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -81,7 +81,7 @@
 }
 
 func (binary *binaryDecorator) getStem(ctx BaseModuleContext) string {
-	stem := ctx.ModuleName()
+	stem := ctx.baseModuleName()
 	if binary.Properties.Stem != "" {
 		stem = binary.Properties.Stem
 	}
@@ -171,7 +171,7 @@
 		}
 		if ctx.TargetPrimary() {
 			binary.baseInstaller.Properties.Symlinks = append(binary.baseInstaller.Properties.Symlinks,
-				ctx.ModuleName())
+				ctx.baseModuleName())
 		}
 	}
 }
diff --git a/cc/cc.go b/cc/cc.go
index b51e13c..529a329 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -19,7 +19,6 @@
 // is handled in builder.go
 
 import (
-	"fmt"
 	"strconv"
 	"strings"
 
@@ -146,6 +145,7 @@
 	sdk() bool
 	sdkVersion() string
 	selectedStl() string
+	baseModuleName() string
 }
 
 type ModuleContext interface {
@@ -354,6 +354,10 @@
 	return ""
 }
 
+func (ctx *moduleContextImpl) baseModuleName() string {
+	return ctx.mod.ModuleBase.BaseModuleName()
+}
+
 func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
 	return &Module{
 		hod:      hod,
@@ -368,6 +372,21 @@
 	return module
 }
 
+func (c *Module) Prebuilt() *android.Prebuilt {
+	if p, ok := c.linker.(prebuiltLinkerInterface); ok {
+		return p.prebuilt()
+	}
+	return nil
+}
+
+func (c *Module) Name() string {
+	name := c.ModuleBase.Name()
+	if p, ok := c.linker.(prebuiltLinkerInterface); ok {
+		name = p.Name(name)
+	}
+	return name
+}
+
 func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
 	ctx := &moduleContext{
 		ModuleContext: actx,
@@ -434,12 +453,12 @@
 			return
 		}
 		c.outputFile = android.OptionalPathForPath(outputFile)
+	}
 
-		if c.installer != nil && !c.Properties.PreventInstall {
-			c.installer.install(ctx, outputFile)
-			if ctx.Failed() {
-				return
-			}
+	if c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid() {
+		c.installer.install(ctx, c.outputFile.Path())
+		if ctx.Failed() {
+			return
 		}
 	}
 }
@@ -792,11 +811,6 @@
 			return
 		}
 
-		if !cc.outputFile.Valid() {
-			ctx.ModuleErrorf("module %q missing output file", name)
-			return
-		}
-
 		if tag == reuseObjTag {
 			depPaths.ObjFiles = append(depPaths.ObjFiles,
 				cc.compiler.(libraryInterface).reuseObjs()...)
@@ -861,11 +875,13 @@
 			depPaths.CrtBegin = linkFile
 		case crtEndDepTag:
 			depPaths.CrtEnd = linkFile
-		default:
-			panic(fmt.Errorf("unknown dependency tag: %s", tag))
 		}
 
 		if ptr != nil {
+			if !linkFile.Valid() {
+				ctx.ModuleErrorf("module %q missing output file", name)
+				return
+			}
 			*ptr = append(*ptr, linkFile.Path())
 		}
 
diff --git a/cc/library.go b/cc/library.go
index cb4dc61..feeb03c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -284,7 +284,7 @@
 func (library *libraryDecorator) getLibName(ctx ModuleContext) string {
 	name := library.libName
 	if name == "" {
-		name = ctx.ModuleName()
+		name = ctx.baseModuleName()
 	}
 
 	if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
new file mode 100644
index 0000000..55775b6
--- /dev/null
+++ b/cc/prebuilt.go
@@ -0,0 +1,72 @@
+// 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"
+
+	"github.com/google/blueprint"
+)
+
+func init() {
+	android.RegisterModuleType("cc_prebuilt_shared_library", prebuiltSharedLibraryFactory)
+}
+
+type prebuiltLinkerInterface interface {
+	Name(string) string
+	prebuilt() *android.Prebuilt
+}
+
+type prebuiltLibraryLinker struct {
+	*libraryDecorator
+	android.Prebuilt
+}
+
+var _ prebuiltLinkerInterface = (*prebuiltLibraryLinker)(nil)
+
+func (p *prebuiltLibraryLinker) prebuilt() *android.Prebuilt {
+	return &p.Prebuilt
+}
+
+func (p *prebuiltLibraryLinker) linkerProps() []interface{} {
+	props := p.libraryDecorator.linkerProps()
+	return append(props, &p.Prebuilt.Properties)
+}
+
+func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
+	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+	// TODO(ccross): verify shared library dependencies
+	if len(p.Prebuilt.Properties.Srcs) > 0 {
+		p.libraryDecorator.exportIncludes(ctx, "-I")
+		p.libraryDecorator.reexportFlags(deps.ReexportedFlags)
+		p.libraryDecorator.reexportDeps(deps.ReexportedFlagsDeps)
+		// TODO(ccross): .toc optimization, stripping, packing
+		return p.Prebuilt.Path(ctx)
+	}
+
+	return nil
+}
+
+func prebuiltSharedLibraryFactory() (blueprint.Module, []interface{}) {
+	module, library := NewLibrary(android.HostAndDeviceSupported, true, false)
+	module.compiler = nil
+
+	prebuilt := &prebuiltLibraryLinker{
+		libraryDecorator: library,
+	}
+	module.linker = prebuilt
+
+	return module.Init()
+}