Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5d1ab1b authored by Kiyoung Kim's avatar Kiyoung Kim
Browse files

Support NDK variant of cc_api_variant

Update cc build logic to support NDK variant of cc_api_variant. Any
cc_api_library with NDK variant of cc_api_variant would be treated as
similar with NDK library.

Bug: 259007436
Test: Cuttlefish vendor build succeeded
Change-Id: I75a7475f4fdcbac779f5aa64e76c60f94ea7ea1a
parent 4a06eea3
Loading
Loading
Loading
Loading
+39 −21
Original line number Diff line number Diff line
@@ -2314,28 +2314,23 @@ func RewriteLibs(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.
	return nonvariantLibs, variantLibs
}

func updateDepsWithApiImports(deps Deps, apiImports multitree.ApiImportInfo) Deps {
	for idx, lib := range deps.SharedLibs {
		deps.SharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
	}

	for idx, lib := range deps.LateSharedLibs {
		deps.LateSharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
	}

	for idx, lib := range deps.RuntimeLibs {
		deps.RuntimeLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
	}

	for idx, lib := range deps.SystemSharedLibs {
		deps.SystemSharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
func rewriteLibsForApiImports(c LinkableInterface, libs []string, replaceList map[string]string, config android.Config) ([]string, []string) {
	nonVariantLibs := []string{}
	variantLibs := []string{}

	for _, lib := range libs {
		replaceLibName := GetReplaceModuleName(lib, replaceList)
		if replaceLibName == lib {
			// Do not handle any libs which are not in API imports
			nonVariantLibs = append(nonVariantLibs, replaceLibName)
		} else if c.UseSdk() && inList(replaceLibName, *getNDKKnownLibs(config)) {
			variantLibs = append(variantLibs, replaceLibName)
		} else {
			nonVariantLibs = append(nonVariantLibs, replaceLibName)
		}

	for idx, lib := range deps.ReexportSharedLibHeaders {
		deps.ReexportSharedLibHeaders[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
	}

	return deps
	return nonVariantLibs, variantLibs
}

func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
@@ -2354,8 +2349,15 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
	deps := c.deps(ctx)
	apiImportInfo := GetApiImports(c, actx)

	apiNdkLibs := []string{}
	apiLateNdkLibs := []string{}

	if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
		deps = updateDepsWithApiImports(deps, apiImportInfo)
		deps.SharedLibs, apiNdkLibs = rewriteLibsForApiImports(c, deps.SharedLibs, apiImportInfo.SharedLibs, ctx.Config())
		deps.LateSharedLibs, apiLateNdkLibs = rewriteLibsForApiImports(c, deps.LateSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
		deps.SystemSharedLibs, _ = rewriteLibsForApiImports(c, deps.SystemSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
		deps.ReexportHeaderLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportHeaderLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
		deps.ReexportSharedLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportSharedLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
	}

	c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
@@ -2542,12 +2544,20 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
		{Mutator: "version", Variation: version},
		{Mutator: "link", Variation: "shared"},
	}, ndkStubDepTag, variantNdkLibs...)
	actx.AddVariationDependencies([]blueprint.Variation{
		{Mutator: "version", Variation: version},
		{Mutator: "link", Variation: "shared"},
	}, ndkStubDepTag, apiNdkLibs...)

	ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version}
	actx.AddVariationDependencies([]blueprint.Variation{
		{Mutator: "version", Variation: version},
		{Mutator: "link", Variation: "shared"},
	}, ndkLateStubDepTag, variantLateNdkLibs...)
	actx.AddVariationDependencies([]blueprint.Variation{
		{Mutator: "version", Variation: version},
		{Mutator: "link", Variation: "shared"},
	}, ndkLateStubDepTag, apiLateNdkLibs...)

	if vndkdep := c.vndkdep; vndkdep != nil {
		if vndkdep.isVndkExt() {
@@ -2601,6 +2611,10 @@ func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to Lin
		}
		return
	}
	// TODO(b/244244438) : Remove this once all variants are implemented
	if ccFrom, ok := from.(*Module); ok && ccFrom.isImportedApiLibrary() {
		return
	}
	if from.SdkVersion() == "" {
		// Platform code can link to anything
		return
@@ -2627,6 +2641,10 @@ func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to Lin
			// the NDK.
			return
		}
		if c.isImportedApiLibrary() {
			// Imported library from the API surface is a stub library built against interface definition.
			return
		}
	}

	if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Module().Name() == "libc++" {
+93 −18
Original line number Diff line number Diff line
@@ -15,14 +15,17 @@
package cc

import (
	"regexp"
	"strings"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
	"android/soong/multitree"
)

var (
	ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
)

func init() {
	RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
}
@@ -45,13 +48,17 @@ func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
	}

	if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
		// Add LLNDK dependencies
		for _, variant := range apiLibrary.properties.Variants {
			if variant == "llndk" {
		// Add LLNDK variant dependency
		if inList("llndk", apiLibrary.properties.Variants) {
			variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
			ctx.AddDependency(m, nil, variantName)
				break
		}
	} else if m.IsSdkVariant() {
		// Add NDK variant dependencies
		targetVariant := "ndk." + m.StubsVersion()
		if inList(targetVariant, apiLibrary.properties.Variants) {
			variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
			ctx.AddDependency(m, nil, variantName)
		}
	}
}
@@ -117,12 +124,31 @@ func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
	}
}

func (d *apiLibraryDecorator) linkerInit(ctx BaseModuleContext) {
	d.baseLinker.linkerInit(ctx)

	if d.hasNDKStubs() {
		// Set SDK version of module as current
		ctx.Module().(*Module).Properties.Sdk_version = StringPtr("current")

		// Add NDK stub as NDK known libs
		name := ctx.ModuleName()

		ndkKnownLibsLock.Lock()
		ndkKnownLibs := getNDKKnownLibs(ctx.Config())
		if !inList(name, *ndkKnownLibs) {
			*ndkKnownLibs = append(*ndkKnownLibs, name)
		}
		ndkKnownLibsLock.Unlock()
	}
}

func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
	m, _ := ctx.Module().(*Module)

	var in android.Path

	if src := proptools.String(d.properties.Src); src != "" {
	if src := String(d.properties.Src); src != "" {
		in = android.PathForModuleSrc(ctx, src)
	}

@@ -149,7 +175,7 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
					variantMod.exportProperties.Export_headers...)

				// Export headers as system include dirs if specified. Mostly for libc
				if proptools.Bool(variantMod.exportProperties.Export_headers_as_system) {
				if Bool(variantMod.exportProperties.Export_headers_as_system) {
					d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
						d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
						d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
@@ -157,6 +183,29 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
				}
			}
		}
	} else if m.IsSdkVariant() {
		// NDK Variant
		apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion())

		var mod android.Module

		ctx.VisitDirectDeps(func(depMod android.Module) {
			if depMod.Name() == apiVariantModule {
				mod = depMod
			}
		})

		if mod != nil {
			variantMod, ok := mod.(*CcApiVariant)
			if ok {
				in = variantMod.Src()

				// Copy NDK properties to cc_api_library module
				d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
					d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
					variantMod.exportProperties.Export_headers...)
			}
		}
	}

	// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
@@ -214,6 +263,14 @@ func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []st

	// TODO(b/244244438) Create more version information for NDK and APEX variations
	// NDK variants

	if m.IsSdkVariant() {
		// TODO(b/249193999) Do not check if module has NDK stubs once all NDK cc_api_library contains ndk variant of cc_api_variant.
		if d.hasNDKStubs() {
			return d.getNdkVersions()
		}
	}

	if m.MinSdkVersion() == "" {
		return nil
	}
@@ -229,14 +286,30 @@ func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []st
}

func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
	return inList("llndk", d.properties.Variants)
}

func (d *apiLibraryDecorator) hasNDKStubs() bool {
	for _, variant := range d.properties.Variants {
		if strings.Contains(variant, "llndk") {
		if ndkVariantRegex.MatchString(variant) {
			return true
		}
	}
	return false
}

func (d *apiLibraryDecorator) getNdkVersions() []string {
	ndkVersions := []string{}

	for _, variant := range d.properties.Variants {
		if match := ndkVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
			ndkVersions = append(ndkVersions, match[1])
		}
	}

	return ndkVersions
}

// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
// header libraries. The module will replace any dependencies to existing
// original header libraries.
@@ -320,18 +393,18 @@ func CcApiVariantFactory() android.Module {
func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	// No need to build

	if proptools.String(v.properties.Src) == "" {
	if String(v.properties.Src) == "" {
		ctx.PropertyErrorf("src", "src is a required property")
	}

	// Skip the existence check of the stub prebuilt file.
	// The file is not guaranteed to exist during Soong analysis.
	// Build orchestrator will be responsible for creating a connected ninja graph.
	v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), proptools.String(v.properties.Src))
	v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), String(v.properties.Src))
}

func (v *CcApiVariant) Name() string {
	version := proptools.String(v.properties.Version)
	version := String(v.properties.Version)
	return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
}

@@ -350,7 +423,9 @@ func BuildApiVariantName(baseName string, variant string, version string) string

// Implement ImageInterface to generate image variants
func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool          { return false }
func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
	return String(v.properties.Variant) == "ndk"
}
func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool       { return false }
func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool  { return false }
@@ -359,7 +434,7 @@ func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []str
	var variations []string
	platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()

	if proptools.String(v.properties.Variant) == "llndk" {
	if String(v.properties.Variant) == "llndk" {
		variations = append(variations, VendorVariationPrefix+platformVndkVersion)
		variations = append(variations, ProductVariationPrefix+platformVndkVersion)
	}
+178 −6
Original line number Diff line number Diff line
@@ -322,16 +322,188 @@ func TestApiLibraryWithLlndkVariant(t *testing.T) {

	ctx := prepareForCcTest.RunTestWithBp(t, bp)

	libfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
	binfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
	libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()

	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport))
	android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))

	libFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
	android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", libFooLibFlags, "libbar_llndk.so")
	binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
	android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar_llndk.so")

	binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
	android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include")
}

func TestApiLibraryWithNdkVariant(t *testing.T) {
	bp := `
		cc_binary {
			name: "binfoo",
			sdk_version: "29",
			srcs: ["binfoo.cc"],
			shared_libs: ["libbar"],
			stl: "c++_shared",
		}

		cc_binary {
			name: "binbaz",
			sdk_version: "30",
			srcs: ["binbaz.cc"],
			shared_libs: ["libbar"],
			stl: "c++_shared",
		}

		cc_api_library {
			name: "libbar",
			// TODO(b/244244438) Remove src property once all variants are implemented.
			src: "libbar.so",
			variants: [
				"ndk.29",
				"ndk.30",
				"ndk.current",
			],
		}

		cc_api_variant {
			name: "libbar",
			variant: "ndk",
			version: "29",
			src: "libbar_ndk_29.so",
			export_headers: ["libbar_ndk_29_include"]
		}

		cc_api_variant {
			name: "libbar",
			variant: "ndk",
			version: "30",
			src: "libbar_ndk_30.so",
			export_headers: ["libbar_ndk_30_include"]
		}

		cc_api_variant {
			name: "libbar",
			variant: "ndk",
			version: "current",
			src: "libbar_ndk_current.so",
			export_headers: ["libbar_ndk_current_include"]
		}

		api_imports {
			name: "api_imports",
			shared_libs: [
				"libbar",
			],
			header_libs: [],
		}
	`

	ctx := prepareForCcTest.RunTestWithBp(t, bp)

	binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
	libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
	libbarApiVariantv29 := ctx.ModuleForTests("libbar.ndk.29.apiimport", "android_arm64_armv8-a_sdk").Module()
	libbarApiImportv30 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_30").Module()
	libbarApiVariantv30 := ctx.ModuleForTests("libbar.ndk.30.apiimport", "android_arm64_armv8-a_sdk").Module()

	android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
	android.AssertBoolEquals(t, "Stub library variant from API surface should be linked with target version", true, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv29))
	android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportv30))
	android.AssertBoolEquals(t, "Stub library variant from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv30))

	binbaz := ctx.ModuleForTests("binbaz", "android_arm64_armv8-a_sdk").Module()

	android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportv30))
	android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))

	binFooLibFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("ld").Args["libFlags"]
	android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar_ndk_29.so")

	binFooCFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("cc").Args["cFlags"]
	android.AssertStringDoesContain(t, "Binary using sdk should include headers from the NDK variant source", binFooCFlags, "-Ilibbar_ndk_29_include")
}

func TestApiLibraryWithMultipleVariants(t *testing.T) {
	bp := `
		cc_binary {
			name: "binfoo",
			sdk_version: "29",
			srcs: ["binfoo.cc"],
			shared_libs: ["libbar"],
			stl: "c++_shared",
		}

		cc_binary {
			name: "binbaz",
			vendor: true,
			srcs: ["binbaz.cc"],
			shared_libs: ["libbar"],
		}

		cc_api_library {
			name: "libbar",
			// TODO(b/244244438) Remove src property once all variants are implemented.
			src: "libbar.so",
			vendor_available: true,
			variants: [
				"llndk",
				"ndk.29",
				"ndk.30",
				"ndk.current",
			],
		}

		cc_api_variant {
			name: "libbar",
			variant: "ndk",
			version: "29",
			src: "libbar_ndk_29.so",
			export_headers: ["libbar_ndk_29_include"]
		}

		cc_api_variant {
			name: "libbar",
			variant: "ndk",
			version: "30",
			src: "libbar_ndk_30.so",
			export_headers: ["libbar_ndk_30_include"]
		}

		cc_api_variant {
			name: "libbar",
			variant: "ndk",
			version: "current",
			src: "libbar_ndk_current.so",
			export_headers: ["libbar_ndk_current_include"]
		}

		cc_api_variant {
			name: "libbar",
			variant: "llndk",
			src: "libbar_llndk.so",
			export_headers: ["libbar_llndk_include"]
		}

		api_imports {
			name: "api_imports",
			shared_libs: [
				"libbar",
			],
			header_libs: [],
		}
	`
	ctx := prepareForCcTest.RunTestWithBp(t, bp)

	binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
	libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
	libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()

	android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
	android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk))

	binbaz := ctx.ModuleForTests("binbaz", "android_vendor.29_arm64_armv8-a").Module()

	android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk))
	android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))

	libFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
	android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", libFooCFlags, "-Ilibbar_llndk_include")
}
+30 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {

	switch m := ctx.Module().(type) {
	case LinkableInterface:
		ccModule, isCcModule := ctx.Module().(*Module)
		if m.AlwaysSdk() {
			if !m.UseSdk() && !m.SplitPerApiLevel() {
				ctx.ModuleErrorf("UseSdk() must return true when AlwaysSdk is set, did the factory forget to set Sdk_version?")
@@ -58,11 +59,32 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {
				modules[1].(*Module).Properties.PreventInstall = true
			}
			ctx.AliasVariation("")
		} else if isCcModule && ccModule.isImportedApiLibrary() {
			apiLibrary, _ := ccModule.linker.(*apiLibraryDecorator)
			if apiLibrary.hasNDKStubs() && ccModule.canUseSdk() {
				// Handle cc_api_library module with NDK stubs and variants only which can use SDK
				modules := ctx.CreateVariations("", "sdk")
				modules[1].(*Module).Properties.IsSdkVariant = true
				if ctx.Config().UnbundledBuildApps() {
					// For an unbundled apps build, hide the platform variant from Make.
					modules[0].(*Module).Properties.HideFromMake = true
					modules[0].(*Module).Properties.PreventInstall = true
				} else {
					// For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when
					// exposed to Make.
					modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
					modules[1].(*Module).Properties.PreventInstall = true
				}
			} else {
			if m, ok := ctx.Module().(*Module); ok {
				ccModule.Properties.Sdk_version = nil
				ctx.CreateVariations("")
				ctx.AliasVariation("")
			}
		} else {
			if isCcModule {
				// Clear the sdk_version property for modules that don't have an SDK variant so
				// later code doesn't get confused by it.
				m.Properties.Sdk_version = nil
				ccModule.Properties.Sdk_version = nil
			}
			ctx.CreateVariations("")
			ctx.AliasVariation("")
@@ -79,6 +101,11 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {
	case *snapshotModule:
		ctx.CreateVariations("")
	case *CcApiVariant:
		ccApiVariant, _ := ctx.Module().(*CcApiVariant)
		if String(ccApiVariant.properties.Variant) == "ndk" {
			ctx.CreateVariations("sdk")
		} else {
			ctx.CreateVariations("")
		}
	}
}