Merge "Collect total number of CPU cores and available RAM for each build."
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 899d339..e58a172 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -442,6 +442,11 @@
 	entries.SubName = ndkLibrarySuffix + "." + c.apiLevel.String()
 	entries.Class = "SHARED_LIBRARIES"
 
+	if !c.buildStubs() {
+		entries.Disabled = true
+		return
+	}
+
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		path, file := filepath.Split(c.installPath.String())
 		stem, suffix, _ := android.SplitFileExt(file)
diff --git a/cc/cc.go b/cc/cc.go
index 8560042..dbe6346 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -45,7 +45,6 @@
 		ctx.BottomUp("sdk", sdkMutator).Parallel()
 		ctx.BottomUp("vndk", VndkMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
-		ctx.BottomUp("ndk_api", NdkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("version_selector", versionSelectorMutator).Parallel()
 		ctx.BottomUp("version", versionMutator).Parallel()
@@ -718,14 +717,9 @@
 	return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
 }
 
-func (c *Module) StubsVersions() []string {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			return library.Properties.Stubs.Versions
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			return library.Properties.Stubs.Versions
-		}
+func (c *Module) StubsVersions(ctx android.BaseMutatorContext) []string {
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.stubsVersions(ctx)
 	}
 	panic(fmt.Errorf("StubsVersions called on non-library module: %q", c.BaseModuleName()))
 }
@@ -754,100 +748,48 @@
 }
 
 func (c *Module) SetBuildStubs() {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			library.MutatedProperties.BuildStubs = true
-			c.Properties.HideFromMake = true
-			c.sanitize = nil
-			c.stl = nil
-			c.Properties.PreventInstall = true
-			return
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			library.MutatedProperties.BuildStubs = true
-			c.Properties.HideFromMake = true
-			c.sanitize = nil
-			c.stl = nil
-			c.Properties.PreventInstall = true
-			return
-		}
-		if _, ok := c.linker.(*llndkStubDecorator); ok {
-			c.Properties.HideFromMake = true
-			return
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		versioned.setBuildStubs()
+		c.Properties.HideFromMake = true
+		c.sanitize = nil
+		c.stl = nil
+		c.Properties.PreventInstall = true
+		return
 	}
 	panic(fmt.Errorf("SetBuildStubs called on non-library module: %q", c.BaseModuleName()))
 }
 
 func (c *Module) BuildStubs() bool {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			return library.buildStubs()
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			return library.buildStubs()
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.buildStubs()
 	}
 	panic(fmt.Errorf("BuildStubs called on non-library module: %q", c.BaseModuleName()))
 }
 
 func (c *Module) SetAllStubsVersions(versions []string) {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		library.MutatedProperties.AllStubsVersions = versions
-		return
-	}
-	if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		library.MutatedProperties.AllStubsVersions = versions
-		return
-	}
-	if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-		llndk.libraryDecorator.MutatedProperties.AllStubsVersions = versions
-		return
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		versioned.setAllStubsVersions(versions)
 	}
 }
 
 func (c *Module) AllStubsVersions() []string {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		return library.MutatedProperties.AllStubsVersions
-	}
-	if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		return library.MutatedProperties.AllStubsVersions
-	}
-	if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-		return llndk.libraryDecorator.MutatedProperties.AllStubsVersions
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.allStubsVersions()
 	}
 	return nil
 }
 
 func (c *Module) SetStubsVersion(version string) {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			library.MutatedProperties.StubsVersion = version
-			return
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			library.MutatedProperties.StubsVersion = version
-			return
-		}
-		if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-			llndk.libraryDecorator.MutatedProperties.StubsVersion = version
-			return
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		versioned.setStubsVersion(version)
+		return
 	}
 	panic(fmt.Errorf("SetStubsVersion called on non-library module: %q", c.BaseModuleName()))
 }
 
 func (c *Module) StubsVersion() string {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			return library.MutatedProperties.StubsVersion
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			return library.MutatedProperties.StubsVersion
-		}
-		if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-			return llndk.libraryDecorator.MutatedProperties.StubsVersion
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.stubsVersion()
 	}
 	panic(fmt.Errorf("StubsVersion called on non-library module: %q", c.BaseModuleName()))
 }
@@ -1085,22 +1027,15 @@
 }
 
 func (c *Module) IsStubs() bool {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		return library.buildStubs()
-	} else if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		return library.buildStubs()
-	} else if _, ok := c.linker.(*llndkStubDecorator); ok {
-		return true
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.buildStubs()
 	}
 	return false
 }
 
 func (c *Module) HasStubsVariants() bool {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		return len(library.Properties.Stubs.Versions) > 0
-	}
-	if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		return len(library.Properties.Stubs.Versions) > 0
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.hasStubsVariants()
 	}
 	return false
 }
@@ -1752,7 +1687,7 @@
 	if m.UseSdk() {
 		return []blueprint.Variation{
 			{Mutator: "sdk", Variation: "sdk"},
-			{Mutator: "ndk_api", Variation: m.SdkVersion()},
+			{Mutator: "version", Variation: m.SdkVersion()},
 		}
 	}
 	return []blueprint.Variation{
@@ -1872,16 +1807,9 @@
 	}
 
 	buildStubs := false
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			if library.buildStubs() {
-				buildStubs = true
-			}
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			if library.buildStubs() {
-				buildStubs = true
-			}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		if versioned.buildStubs() {
+			buildStubs = true
 		}
 	}
 
@@ -2025,11 +1953,10 @@
 		actx.AddDependency(c, depTag, gen)
 	}
 
-	actx.AddVariationDependencies(nil, objDepTag, deps.ObjFiles...)
-
 	vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
 
 	crtVariations := GetCrtVariations(ctx, c)
+	actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
 	if deps.CrtBegin != "" {
 		actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
 			rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
@@ -2049,13 +1976,13 @@
 
 	ndkStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, ndk: true, makeSuffix: "." + version}
 	actx.AddVariationDependencies([]blueprint.Variation{
-		{Mutator: "ndk_api", Variation: version},
+		{Mutator: "version", Variation: version},
 		{Mutator: "link", Variation: "shared"},
 	}, ndkStubDepTag, variantNdkLibs...)
 
 	ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version}
 	actx.AddVariationDependencies([]blueprint.Variation{
-		{Mutator: "ndk_api", Variation: version},
+		{Mutator: "version", Variation: version},
 		{Mutator: "link", Variation: "shared"},
 	}, ndkLateStubDepTag, variantLateNdkLibs...)
 
diff --git a/cc/library.go b/cc/library.go
index ea12818..090abf9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -349,7 +349,7 @@
 	// Location of the file that should be copied to dist dir when requested
 	distFile android.Path
 
-	versionScriptPath android.ModuleGenPath
+	versionScriptPath android.OptionalPath
 
 	post_install_cmds []string
 
@@ -358,6 +358,8 @@
 	useCoreVariant       bool
 	checkSameCoreVariant bool
 
+	skipAPIDefine bool
+
 	// Decorated interfaces
 	*baseCompiler
 	*baseLinker
@@ -611,7 +613,7 @@
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
 	if library.buildStubs() {
 		objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex")
-		library.versionScriptPath = versionScript
+		library.versionScriptPath = android.OptionalPathForPath(versionScript)
 		return objs
 	}
 
@@ -661,6 +663,8 @@
 }
 
 type libraryInterface interface {
+	versionedInterface
+
 	static() bool
 	shared() bool
 	objs() Objects
@@ -681,6 +685,21 @@
 	availableFor(string) bool
 }
 
+type versionedInterface interface {
+	buildStubs() bool
+	setBuildStubs()
+	hasStubsVariants() bool
+	setStubsVersion(string)
+	stubsVersion() string
+
+	stubsVersions(ctx android.BaseMutatorContext) []string
+	setAllStubsVersions([]string)
+	allStubsVersions() []string
+}
+
+var _ libraryInterface = (*libraryDecorator)(nil)
+var _ versionedInterface = (*libraryDecorator)(nil)
+
 func (library *libraryDecorator) getLibNameHelper(baseModuleName string, useVndk bool) string {
 	name := library.libName
 	if name == "" {
@@ -916,10 +935,10 @@
 			linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
 		}
 	}
-	if library.buildStubs() {
+	if library.versionScriptPath.Valid() {
 		linkerScriptFlags := "-Wl,--version-script," + library.versionScriptPath.String()
 		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlags)
-		linkerDeps = append(linkerDeps, library.versionScriptPath)
+		linkerDeps = append(linkerDeps, library.versionScriptPath.Path())
 	}
 
 	fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
@@ -1185,8 +1204,8 @@
 		library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
 	}
 
-	if library.buildStubs() {
-		library.reexportFlags("-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion())
+	if library.buildStubs() && !library.skipAPIDefine {
+		library.reexportFlags("-D" + versioningMacroName(ctx.baseModuleName()) + "=" + library.stubsVersion())
 	}
 
 	library.flagExporter.setProvider(ctx)
@@ -1353,10 +1372,34 @@
 	return nil
 }
 
+func (library *libraryDecorator) hasStubsVariants() bool {
+	return len(library.Properties.Stubs.Versions) > 0
+}
+
+func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+	return library.Properties.Stubs.Versions
+}
+
+func (library *libraryDecorator) setStubsVersion(version string) {
+	library.MutatedProperties.StubsVersion = version
+}
+
 func (library *libraryDecorator) stubsVersion() string {
 	return library.MutatedProperties.StubsVersion
 }
 
+func (library *libraryDecorator) setBuildStubs() {
+	library.MutatedProperties.BuildStubs = true
+}
+
+func (library *libraryDecorator) setAllStubsVersions(versions []string) {
+	library.MutatedProperties.AllStubsVersions = versions
+}
+
+func (library *libraryDecorator) allStubsVersions() []string {
+	return library.MutatedProperties.AllStubsVersions
+}
+
 func (library *libraryDecorator) isLatestStubVersion() bool {
 	versions := library.Properties.Stubs.Versions
 	return versions[len(versions)-1] == library.stubsVersion()
@@ -1573,20 +1616,33 @@
 	mctx.CreateAliasVariation("latest", latestVersion)
 }
 
+func createPerApiVersionVariations(mctx android.BottomUpMutatorContext, minSdkVersion string) {
+	from, err := nativeApiLevelFromUser(mctx, minSdkVersion)
+	if err != nil {
+		mctx.PropertyErrorf("min_sdk_version", err.Error())
+		return
+	}
+
+	versionStrs := ndkLibraryVersions(mctx, from)
+	modules := mctx.CreateLocalVariations(versionStrs...)
+
+	for i, module := range modules {
+		module.(*Module).Properties.Sdk_version = StringPtr(versionStrs[i])
+	}
+}
+
 func CanBeOrLinkAgainstVersionVariants(module interface {
 	Host() bool
 	InRamdisk() bool
 	InRecovery() bool
-	UseSdk() bool
 }) bool {
-	return !module.Host() && !module.InRamdisk() && !module.InRecovery() && !module.UseSdk()
+	return !module.Host() && !module.InRamdisk() && !module.InRecovery()
 }
 
 func CanBeVersionVariant(module interface {
 	Host() bool
 	InRamdisk() bool
 	InRecovery() bool
-	UseSdk() bool
 	CcLibraryInterface() bool
 	Shared() bool
 	Static() bool
@@ -1599,27 +1655,18 @@
 // and propagates the value from implementation libraries to llndk libraries with the same name.
 func versionSelectorMutator(mctx android.BottomUpMutatorContext) {
 	if library, ok := mctx.Module().(LinkableInterface); ok && CanBeVersionVariant(library) {
-		if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 {
-
-			versions := library.StubsVersions()
-			normalizeVersions(mctx, versions)
-			if mctx.Failed() {
+		if library.CcLibraryInterface() && library.BuildSharedVariant() {
+			versions := library.StubsVersions(mctx)
+			if len(versions) > 0 {
+				normalizeVersions(mctx, versions)
+				if mctx.Failed() {
+					return
+				}
+				// Set the versions on the pre-mutated module so they can be read by any llndk modules that
+				// depend on the implementation library and haven't been mutated yet.
+				library.SetAllStubsVersions(versions)
 				return
 			}
-			// Set the versions on the pre-mutated module so they can be read by any llndk modules that
-			// depend on the implementation library and haven't been mutated yet.
-			library.SetAllStubsVersions(versions)
-			return
-		}
-
-		if c, ok := library.(*Module); ok && c.IsStubs() {
-			// Get the versions from the implementation module.
-			impls := mctx.GetDirectDepsWithTag(llndkImplDep)
-			if len(impls) > 1 {
-				panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls)))
-			} else if len(impls) == 1 {
-				c.SetAllStubsVersions(impls[0].(*Module).AllStubsVersions())
-			}
 		}
 	}
 }
@@ -1629,6 +1676,16 @@
 func versionMutator(mctx android.BottomUpMutatorContext) {
 	if library, ok := mctx.Module().(LinkableInterface); ok && CanBeVersionVariant(library) {
 		createVersionVariations(mctx, library.AllStubsVersions())
+		return
+	}
+
+	if m, ok := mctx.Module().(*Module); ok {
+		if m.SplitPerApiLevel() && m.IsSdkVariant() {
+			if mctx.Os() != android.Android {
+				return
+			}
+			createPerApiVersionVariations(mctx, m.MinSdkVersion())
+		}
 	}
 }
 
diff --git a/cc/linkable.go b/cc/linkable.go
index 21e6f9b..4eb7220 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -16,7 +16,7 @@
 
 	NonCcVariants() bool
 
-	StubsVersions() []string
+	StubsVersions(android.BaseMutatorContext) []string
 	BuildStubs() bool
 	SetBuildStubs()
 	SetStubsVersion(string)
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index a429063..4425a10 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -15,17 +15,14 @@
 package cc
 
 import (
+	"fmt"
 	"path/filepath"
 	"strings"
 
 	"android/soong/android"
-
-	"github.com/google/blueprint"
 )
 
-var llndkImplDep = struct {
-	blueprint.DependencyTag
-}{}
+var llndkImplDep = dependencyTag{name: "llndk impl"}
 
 var (
 	llndkLibrarySuffix = ".llndk"
@@ -72,9 +69,6 @@
 
 	Properties llndkLibraryProperties
 
-	exportHeadersTimestamp android.OptionalPath
-	versionScriptPath      android.ModuleGenPath
-
 	movedToApex bool
 }
 
@@ -93,7 +87,9 @@
 		vndkVer = stub.stubsVersion()
 	}
 	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
-	stub.versionScriptPath = versionScript
+	if !Bool(stub.Properties.Unversioned) {
+		stub.versionScriptPath = android.OptionalPathForPath(versionScript)
+	}
 	return objs
 }
 
@@ -142,12 +138,6 @@
 		stub.movedToApex = implApexModule.DirectlyInAnyApex()
 	}
 
-	if !Bool(stub.Properties.Unversioned) {
-		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
-		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
-		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
-	}
-
 	if len(stub.Properties.Export_preprocessed_headers) > 0 {
 		genHeaderOutDir := android.PathForModuleGen(ctx, "include")
 
@@ -170,10 +160,6 @@
 		stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
 	}
 
-	if stub.stubsVersion() != "" {
-		stub.reexportFlags("-D" + versioningMacroName(ctx.baseModuleName()) + "=" + stub.stubsVersion())
-	}
-
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
 }
 
@@ -181,6 +167,21 @@
 	return false
 }
 
+func (stub *llndkStubDecorator) buildStubs() bool {
+	return true
+}
+
+func (stub *llndkStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+	// Get the versions from the implementation module.
+	impls := ctx.GetDirectDepsWithTag(llndkImplDep)
+	if len(impls) > 1 {
+		panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls)))
+	} else if len(impls) == 1 {
+		return impls[0].(*Module).AllStubsVersions()
+	}
+	return nil
+}
+
 func NewLLndkStubLibrary() *Module {
 	module, library := NewLibrary(android.DeviceSupported)
 	library.BuildOnlyShared()
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 5682d1c..f2ad652 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -80,9 +80,6 @@
 	// https://github.com/android-ndk/ndk/issues/265.
 	Unversioned_until *string
 
-	// Use via apiLevel on the stubDecorator.
-	ApiLevel string `blueprint:"mutated"`
-
 	// True if this API is not yet ready to be shipped in the NDK. It will be
 	// available in the platform for testing, but will be excluded from the
 	// sysroot provided to the NDK proper.
@@ -107,9 +104,7 @@
 	return stub.apiLevel.GreaterThanOrEqualTo(stub.unversionedUntil)
 }
 
-func generatePerApiVariants(ctx android.BottomUpMutatorContext, m *Module,
-	from android.ApiLevel, perSplit func(*Module, android.ApiLevel)) {
-
+func ndkLibraryVersions(ctx android.BaseMutatorContext, from android.ApiLevel) []string {
 	var versions []android.ApiLevel
 	versionStrs := []string{}
 	for _, version := range ctx.Config().AllSupportedApiLevels() {
@@ -118,56 +113,26 @@
 			versionStrs = append(versionStrs, version.String())
 		}
 	}
-	versions = append(versions, android.FutureApiLevel)
 	versionStrs = append(versionStrs, android.FutureApiLevel.String())
 
-	modules := ctx.CreateVariations(versionStrs...)
-	for i, module := range modules {
-		perSplit(module.(*Module), versions[i])
-	}
+	return versionStrs
 }
 
-func NdkApiMutator(ctx android.BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(*Module); ok {
-		if m.Enabled() {
-			if compiler, ok := m.compiler.(*stubDecorator); ok {
-				if ctx.Os() != android.Android {
-					// These modules are always android.DeviceEnabled only, but
-					// those include Fuchsia devices, which we don't support.
-					ctx.Module().Disable()
-					return
-				}
-				firstVersion, err := nativeApiLevelFromUser(ctx,
-					String(compiler.properties.First_version))
-				if err != nil {
-					ctx.PropertyErrorf("first_version", err.Error())
-					return
-				}
-				generatePerApiVariants(ctx, m, firstVersion,
-					func(m *Module, version android.ApiLevel) {
-						m.compiler.(*stubDecorator).properties.ApiLevel =
-							version.String()
-					})
-			} else if m.SplitPerApiLevel() && m.IsSdkVariant() {
-				if ctx.Os() != android.Android {
-					return
-				}
-				from, err := nativeApiLevelFromUser(ctx, m.MinSdkVersion())
-				if err != nil {
-					ctx.PropertyErrorf("min_sdk_version", err.Error())
-					return
-				}
-				generatePerApiVariants(ctx, m, from,
-					func(m *Module, version android.ApiLevel) {
-						m.Properties.Sdk_version = StringPtr(version.String())
-					})
-			}
-		}
+func (this *stubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+	if !ctx.Module().Enabled() {
+		return nil
 	}
+	firstVersion, err := nativeApiLevelFromUser(ctx,
+		String(this.properties.First_version))
+	if err != nil {
+		ctx.PropertyErrorf("first_version", err.Error())
+		return nil
+	}
+	return ndkLibraryVersions(ctx, firstVersion)
 }
 
 func (this *stubDecorator) initializeProperties(ctx BaseModuleContext) bool {
-	this.apiLevel = nativeApiLevelOrPanic(ctx, this.properties.ApiLevel)
+	this.apiLevel = nativeApiLevelOrPanic(ctx, this.stubsVersion())
 
 	var err error
 	this.firstVersion, err = nativeApiLevelFromUser(ctx,
@@ -280,6 +245,11 @@
 		ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
 	}
 
+	if !c.buildStubs() {
+		// NDK libraries have no implementation variant, nothing to do
+		return Objects{}
+	}
+
 	if !c.initializeProperties(ctx) {
 		// Emits its own errors, so we don't need to.
 		return Objects{}
@@ -311,12 +281,18 @@
 func (stub *stubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
 	objs Objects) android.Path {
 
+	if !stub.buildStubs() {
+		// NDK libraries have no implementation variant, nothing to do
+		return nil
+	}
+
 	if shouldUseVersionScript(ctx, stub) {
 		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
 		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
 		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
 	}
 
+	stub.libraryDecorator.skipAPIDefine = true
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
 }
 
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 56fd54b..b6733c2 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -131,7 +131,7 @@
 		}
 
 		if m, ok := module.(*Module); ok {
-			if installer, ok := m.installer.(*stubDecorator); ok {
+			if installer, ok := m.installer.(*stubDecorator); ok && m.BuildStubs() {
 				if ctx.Config().ExcludeDraftNdkApis() &&
 					installer.properties.Draft {
 					return
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 8e35679..664cb51 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -214,6 +214,13 @@
 		Output: p.outputFilePath,
 		Input:  p.sourceFilePath,
 	})
+
+	if p.Installable() {
+		installPath := ctx.InstallFile(p.installDirPath, p.outputFilePath.Base(), p.outputFilePath)
+		for _, sl := range p.properties.Symlinks {
+			ctx.InstallSymlink(p.installDirPath, sl, installPath)
+		}
+	}
 }
 
 func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/rust/rust.go b/rust/rust.go
index 29606fa..4496e33 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -500,7 +500,7 @@
 	return mod
 }
 
-func (mod *Module) StubsVersions() []string {
+func (mod *Module) StubsVersions(ctx android.BaseMutatorContext) []string {
 	// For now, Rust has no stubs versions.
 	if mod.compiler != nil {
 		if _, ok := mod.compiler.(libraryInterface); ok {