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/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()
+}