Generate NDK sysroots from the platform build.

The list of migrated libraries is currently empty. Libraries will be
migrated as follow up patches.

Test: Migrated libc to this system and everything still builds.
      build.ninja shows libraries being built and used and headers are
      collected for the sysroot.
Bug: http://b/27533932
Change-Id: Iaba00543c1390f432befe0eed768ed3fbb8a9b96
diff --git a/cc/cc.go b/cc/cc.go
index 60bc4d4..12d9ed7 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -58,6 +58,7 @@
 	// the Go initialization order because this package depends on common, so common's init
 	// functions will run first.
 	android.RegisterBottomUpMutator("link", linkageMutator)
+	android.RegisterBottomUpMutator("ndk_api", ndkApiMutator)
 	android.RegisterBottomUpMutator("test_per_src", testPerSrcMutator)
 	android.RegisterBottomUpMutator("deps", depsMutator)
 
@@ -70,6 +71,10 @@
 
 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
@@ -555,6 +560,8 @@
 	crtBeginDepTag     = dependencyTag{name: "crtbegin"}
 	crtEndDepTag       = dependencyTag{name: "crtend"}
 	reuseObjTag        = dependencyTag{name: "reuse objects"}
+	ndkStubDepTag      = dependencyTag{name: "ndk stub", library: true}
+	ndkLateStubDepTag  = dependencyTag{name: "ndk late stub", library: true}
 )
 
 // Module contains the properties and members used by all C/C++ module types, and implements
@@ -883,20 +890,40 @@
 	c.Properties.AndroidMkSharedLibs = append(c.Properties.AndroidMkSharedLibs, deps.SharedLibs...)
 	c.Properties.AndroidMkSharedLibs = append(c.Properties.AndroidMkSharedLibs, deps.LateSharedLibs...)
 
+	variantNdkLibs := []string{}
+	variantLateNdkLibs := []string{}
 	if ctx.sdk() {
-		version := "." + ctx.sdkVersion()
+		version := ctx.sdkVersion()
 
-		rewriteNdkLibs := func(list []string) []string {
-			for i, entry := range list {
+		// Rewrites the names of shared libraries into the names of the NDK
+		// libraries where appropriate. This returns two slices.
+		//
+		// The first is a list of non-variant shared libraries (either rewritten
+		// NDK libraries to the modules in prebuilts/ndk, or not rewritten
+		// because they are not NDK libraries).
+		//
+		// The second is a list of ndk_library modules. These need to be
+		// separated because they are a variation dependency and must be added
+		// in a different manner.
+		rewriteNdkLibs := func(list []string) ([]string, []string) {
+			variantLibs := []string{}
+			nonvariantLibs := []string{}
+			for _, entry := range list {
 				if inList(entry, ndkPrebuiltSharedLibraries) {
-					list[i] = "ndk_" + entry + version
+					if !inList(entry, ndkMigratedLibs) {
+						nonvariantLibs = append(nonvariantLibs, entry+".ndk."+version)
+					} else {
+						variantLibs = append(variantLibs, entry+ndkLibrarySuffix)
+					}
+				} else {
+					nonvariantLibs = append(variantLibs, entry)
 				}
 			}
-			return list
+			return nonvariantLibs, variantLibs
 		}
 
-		deps.SharedLibs = rewriteNdkLibs(deps.SharedLibs)
-		deps.LateSharedLibs = rewriteNdkLibs(deps.LateSharedLibs)
+		deps.SharedLibs, variantNdkLibs = rewriteNdkLibs(deps.SharedLibs)
+		deps.LateSharedLibs, variantLateNdkLibs = rewriteNdkLibs(deps.LateSharedLibs)
 	}
 
 	actx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, wholeStaticDepTag,
@@ -935,6 +962,12 @@
 	if deps.CrtEnd != "" {
 		actx.AddDependency(c, crtEndDepTag, deps.CrtEnd)
 	}
+
+	version := ctx.sdkVersion()
+	actx.AddVariationDependencies([]blueprint.Variation{
+		{"ndk_api", version}, {"link", "shared"}}, ndkStubDepTag, variantNdkLibs...)
+	actx.AddVariationDependencies([]blueprint.Variation{
+		{"ndk_api", version}, {"link", "shared"}}, ndkLateStubDepTag, variantLateNdkLibs...)
 }
 
 func depsMutator(ctx android.BottomUpMutatorContext) {
@@ -990,6 +1023,11 @@
 			// These are allowed, but don't set sdk_version
 			return true
 		}
+		if _, ok := to.linker.(*stubLinker); ok {
+			// These aren't real libraries, but are the stub shared libraries that are included in
+			// the NDK.
+			return true
+		}
 		return to.Properties.Sdk_version != ""
 	}
 
@@ -1073,9 +1111,9 @@
 		var depPtr *android.Paths
 
 		switch tag {
-		case sharedDepTag, sharedExportDepTag:
+		case ndkStubDepTag, sharedDepTag, sharedExportDepTag:
 			depPtr = &depPaths.SharedLibs
-		case lateSharedDepTag:
+		case lateSharedDepTag, ndkLateStubDepTag:
 			depPtr = &depPaths.LateSharedLibs
 		case staticDepTag, staticExportDepTag:
 			depPtr = &depPaths.StaticLibs
@@ -1190,6 +1228,30 @@
 		}...)
 	}
 
+	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
@@ -1310,11 +1372,22 @@
 	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, deps.GeneratedHeaders)
+		deps.GeneratedSources, pathDeps)
 
 	if ctx.Failed() {
 		return nil
@@ -1595,14 +1668,17 @@
 	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, deps.GeneratedHeaders)...)
+			nil, pathDeps)...)
 	} else {
 		objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceSharedLibrary,
 			library.Properties.Shared.Srcs, library.Properties.Shared.Exclude_srcs,
-			nil, deps.GeneratedHeaders)...)
+			nil, pathDeps)...)
 	}
 
 	return objFiles
@@ -1626,6 +1702,10 @@
 
 	// 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)
@@ -1646,7 +1726,10 @@
 }
 
 func (library *libraryLinker) getLibName(ctx ModuleContext) string {
-	name := ctx.ModuleName()
+	name := library.libName
+	if name == "" {
+		name = ctx.ModuleName()
+	}
 
 	if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
 		if !strings.HasSuffix(name, "-host") {
@@ -2634,10 +2717,6 @@
 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.
-	if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
-		ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
-	}
-
 	ndk.exportIncludes(ctx, "-isystem")
 
 	return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),