diff options
Diffstat (limited to 'cc')
-rw-r--r-- | cc/cc.go | 8 | ||||
-rw-r--r-- | cc/ccdeps.go | 35 | ||||
-rw-r--r-- | cc/config/global.go | 4 | ||||
-rw-r--r-- | cc/library.go | 329 | ||||
-rw-r--r-- | cc/library_stub.go | 2 | ||||
-rw-r--r-- | cc/ndk_library.go | 4 | ||||
-rw-r--r-- | cc/sdk.go | 140 |
7 files changed, 328 insertions, 194 deletions
@@ -48,10 +48,10 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_defaults", defaultsFactory) ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("sdk", sdkMutator).Parallel() + ctx.Transition("sdk", &sdkTransitionMutator{}) ctx.BottomUp("llndk", llndkMutator).Parallel() - ctx.BottomUp("link", LinkageMutator).Parallel() - ctx.BottomUp("version", versionMutator).Parallel() + ctx.Transition("link", &linkageTransitionMutator{}) + ctx.Transition("version", &versionTransitionMutator{}) ctx.BottomUp("begin", BeginMutator).Parallel() }) @@ -1867,8 +1867,10 @@ var ( "libdl": true, "libz": true, // art apex + // TODO(b/234351700): Remove this when com.android.art.debug is gone. "libandroidio": true, "libdexfile": true, + "libdexfiled": true, // com.android.art.debug only "libnativebridge": true, "libnativehelper": true, "libnativeloader": true, diff --git a/cc/ccdeps.go b/cc/ccdeps.go index d30abbab7..469fe31fa 100644 --- a/cc/ccdeps.go +++ b/cc/ccdeps.go @@ -85,9 +85,8 @@ func (c *ccdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCon moduleDeps := ccDeps{} moduleInfos := map[string]ccIdeInfo{} - // Track which projects have already had CMakeLists.txt generated to keep the first - // variant for each project. - seenProjects := map[string]bool{} + // Track if best variant (device arch match) has been found. + bestVariantFound := map[string]bool{} pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/") moduleDeps.C_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cClang) @@ -96,7 +95,7 @@ func (c *ccdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCon ctx.VisitAllModules(func(module android.Module) { if ccModule, ok := module.(*Module); ok { if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok { - generateCLionProjectData(ctx, compiledModule, ccModule, seenProjects, moduleInfos) + generateCLionProjectData(ctx, compiledModule, ccModule, bestVariantFound, moduleInfos) } } }) @@ -180,26 +179,30 @@ func parseCompilerCCParameters(ctx android.SingletonContext, params []string) cc } func generateCLionProjectData(ctx android.SingletonContext, compiledModule CompiledInterface, - ccModule *Module, seenProjects map[string]bool, moduleInfos map[string]ccIdeInfo) { + ccModule *Module, bestVariantFound map[string]bool, moduleInfos map[string]ccIdeInfo) { + moduleName := ccModule.ModuleBase.Name() srcs := compiledModule.Srcs() - if len(srcs) == 0 { + + // Skip if best variant has already been found. + if bestVariantFound[moduleName] { return } - // Only keep the DeviceArch variant module. - if ctx.DeviceConfig().DeviceArch() != ccModule.ModuleBase.Arch().ArchType.Name { + // Skip if sources are empty. + if len(srcs) == 0 { return } - clionProjectLocation := getCMakeListsForModule(ccModule, ctx) - if seenProjects[clionProjectLocation] { + // Check if device arch matches, in which case this is the best variant and takes precedence. + if ccModule.Device() && ccModule.ModuleBase.Arch().ArchType.Name == ctx.DeviceConfig().DeviceArch() { + bestVariantFound[moduleName] = true + } else if _, ok := moduleInfos[moduleName]; ok { + // Skip because this isn't the best variant and a previous one has already been added. + // Heuristically, ones that appear first are likely to be more relevant. return } - seenProjects[clionProjectLocation] = true - - name := ccModule.ModuleBase.Name() - dpInfo := moduleInfos[name] + dpInfo := ccIdeInfo{} dpInfo.Path = append(dpInfo.Path, path.Dir(ctx.BlueprintFile(ccModule))) dpInfo.Srcs = append(dpInfo.Srcs, srcs.Strings()...) @@ -216,9 +219,9 @@ func generateCLionProjectData(ctx android.SingletonContext, compiledModule Compi dpInfo.Local_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CppFlags) dpInfo.System_include_flags = parseCompilerCCParameters(ctx, ccModule.flags.SystemIncludeFlags) - dpInfo.Module_name = name + dpInfo.Module_name = moduleName - moduleInfos[name] = dpInfo + moduleInfos[moduleName] = dpInfo } type Deal struct { diff --git a/cc/config/global.go b/cc/config/global.go index 62a4765f4..bf2502fcf 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -397,8 +397,8 @@ var ( // prebuilts/clang default settings. ClangDefaultBase = "prebuilts/clang/host" - ClangDefaultVersion = "clang-r522817" - ClangDefaultShortVersion = "18" + ClangDefaultVersion = "clang-r530567" + ClangDefaultShortVersion = "19" // Directories with warnings from Android.bp files. WarningAllowedProjects = []string{ diff --git a/cc/library.go b/cc/library.go index 560b1ae40..6dd5b5615 100644 --- a/cc/library.go +++ b/cc/library.go @@ -19,6 +19,7 @@ import ( "io" "path/filepath" "regexp" + "slices" "strconv" "strings" "sync" @@ -711,7 +712,7 @@ type versionedInterface interface { setStubsVersion(string) stubsVersion() string - stubsVersions(ctx android.BaseMutatorContext) []string + stubsVersions(ctx android.BaseModuleContext) []string setAllStubsVersions([]string) allStubsVersions() []string @@ -1903,7 +1904,7 @@ func (library *libraryDecorator) isStubsImplementationRequired() bool { return BoolDefault(library.Properties.Stubs.Implementation_installable, true) } -func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string { +func (library *libraryDecorator) stubsVersions(ctx android.BaseModuleContext) []string { if !library.hasStubsVariants() { return nil } @@ -2064,26 +2065,26 @@ func NewLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) // connects a shared library to a static library in order to reuse its .o files to avoid // compiling source files twice. -func reuseStaticLibrary(mctx android.BottomUpMutatorContext, static, shared *Module) { - if staticCompiler, ok := static.compiler.(*libraryDecorator); ok { - sharedCompiler := shared.compiler.(*libraryDecorator) +func reuseStaticLibrary(ctx android.BottomUpMutatorContext, shared *Module) { + if sharedCompiler, ok := shared.compiler.(*libraryDecorator); ok { // Check libraries in addition to cflags, since libraries may be exporting different // include directories. - if len(staticCompiler.StaticProperties.Static.Cflags.GetOrDefault(mctx, nil)) == 0 && - len(sharedCompiler.SharedProperties.Shared.Cflags.GetOrDefault(mctx, nil)) == 0 && - len(staticCompiler.StaticProperties.Static.Whole_static_libs) == 0 && + if len(sharedCompiler.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)) == 0 && + len(sharedCompiler.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)) == 0 && + len(sharedCompiler.StaticProperties.Static.Whole_static_libs) == 0 && len(sharedCompiler.SharedProperties.Shared.Whole_static_libs) == 0 && - len(staticCompiler.StaticProperties.Static.Static_libs) == 0 && + len(sharedCompiler.StaticProperties.Static.Static_libs) == 0 && len(sharedCompiler.SharedProperties.Shared.Static_libs) == 0 && - len(staticCompiler.StaticProperties.Static.Shared_libs) == 0 && + len(sharedCompiler.StaticProperties.Static.Shared_libs) == 0 && len(sharedCompiler.SharedProperties.Shared.Shared_libs) == 0 && // Compare System_shared_libs properties with nil because empty lists are // semantically significant for them. - staticCompiler.StaticProperties.Static.System_shared_libs == nil && + sharedCompiler.StaticProperties.Static.System_shared_libs == nil && sharedCompiler.SharedProperties.Shared.System_shared_libs == nil { - mctx.AddInterVariantDependency(reuseObjTag, shared, static) + // TODO: namespaces? + ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, reuseObjTag, ctx.ModuleName()) sharedCompiler.baseCompiler.Properties.OriginalSrcs = sharedCompiler.baseCompiler.Properties.Srcs sharedCompiler.baseCompiler.Properties.Srcs = nil @@ -2091,19 +2092,21 @@ func reuseStaticLibrary(mctx android.BottomUpMutatorContext, static, shared *Mod } // This dep is just to reference static variant from shared variant - mctx.AddInterVariantDependency(staticVariantTag, shared, static) + ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, staticVariantTag, ctx.ModuleName()) } } -// LinkageMutator adds "static" or "shared" variants for modules depending +// linkageTransitionMutator adds "static" or "shared" variants for modules depending // on whether the module can be built as a static library or a shared library. -func LinkageMutator(mctx android.BottomUpMutatorContext) { +type linkageTransitionMutator struct{} + +func (linkageTransitionMutator) Split(ctx android.BaseModuleContext) []string { ccPrebuilt := false - if m, ok := mctx.Module().(*Module); ok && m.linker != nil { + if m, ok := ctx.Module().(*Module); ok && m.linker != nil { _, ccPrebuilt = m.linker.(prebuiltLibraryInterface) } if ccPrebuilt { - library := mctx.Module().(*Module).linker.(prebuiltLibraryInterface) + library := ctx.Module().(*Module).linker.(prebuiltLibraryInterface) // Differentiate between header only and building an actual static/shared library buildStatic := library.buildStatic() @@ -2112,75 +2115,118 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { // Always create both the static and shared variants for prebuilt libraries, and then disable the one // that is not being used. This allows them to share the name of a cc_library module, which requires that // all the variants of the cc_library also exist on the prebuilt. - modules := mctx.CreateLocalVariations("static", "shared") - static := modules[0].(*Module) - shared := modules[1].(*Module) - - static.linker.(prebuiltLibraryInterface).setStatic() - shared.linker.(prebuiltLibraryInterface).setShared() - - if buildShared { - mctx.AliasVariation("shared") - } else if buildStatic { - mctx.AliasVariation("static") - } - - if !buildStatic { - static.linker.(prebuiltLibraryInterface).disablePrebuilt() - } - if !buildShared { - shared.linker.(prebuiltLibraryInterface).disablePrebuilt() - } + return []string{"static", "shared"} } else { // Header only } - - } else if library, ok := mctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface() || library.RustLibraryInterface()) { + } else if library, ok := ctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface() || library.RustLibraryInterface()) { // Non-cc.Modules may need an empty variant for their mutators. variations := []string{} if library.NonCcVariants() { variations = append(variations, "") } isLLNDK := false - if m, ok := mctx.Module().(*Module); ok { + if m, ok := ctx.Module().(*Module); ok { isLLNDK = m.IsLlndk() } buildStatic := library.BuildStaticVariant() && !isLLNDK buildShared := library.BuildSharedVariant() if buildStatic && buildShared { - variations := append([]string{"static", "shared"}, variations...) - - modules := mctx.CreateLocalVariations(variations...) - static := modules[0].(LinkableInterface) - shared := modules[1].(LinkableInterface) - static.SetStatic() - shared.SetShared() - - if _, ok := library.(*Module); ok { - reuseStaticLibrary(mctx, static.(*Module), shared.(*Module)) - } - mctx.AliasVariation("shared") + variations = append([]string{"static", "shared"}, variations...) + return variations } else if buildStatic { - variations := append([]string{"static"}, variations...) - - modules := mctx.CreateLocalVariations(variations...) - modules[0].(LinkableInterface).SetStatic() - mctx.AliasVariation("static") + variations = append([]string{"static"}, variations...) } else if buildShared { - variations := append([]string{"shared"}, variations...) + variations = append([]string{"shared"}, variations...) + } + + if len(variations) > 0 { + return variations + } + } + return []string{""} +} - modules := mctx.CreateLocalVariations(variations...) - modules[0].(LinkableInterface).SetShared() - mctx.AliasVariation("shared") - } else if len(variations) > 0 { - mctx.CreateLocalVariations(variations...) - mctx.AliasVariation(variations[0]) +func (linkageTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + return "" +} + +func (linkageTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + ccPrebuilt := false + if m, ok := ctx.Module().(*Module); ok && m.linker != nil { + _, ccPrebuilt = m.linker.(prebuiltLibraryInterface) + } + if ccPrebuilt { + if incomingVariation != "" { + return incomingVariation } - if library.BuildRlibVariant() && library.IsRustFFI() && !buildStatic { + library := ctx.Module().(*Module).linker.(prebuiltLibraryInterface) + if library.buildShared() { + return "shared" + } else if library.buildStatic() { + return "static" + } + return "" + } else if library, ok := ctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() { + isLLNDK := false + if m, ok := ctx.Module().(*Module); ok { + isLLNDK = m.IsLlndk() + } + buildStatic := library.BuildStaticVariant() && !isLLNDK + buildShared := library.BuildSharedVariant() + if library.BuildRlibVariant() && library.IsRustFFI() && !buildStatic && (incomingVariation == "static" || incomingVariation == "") { // Rust modules do not build static libs, but rlibs are used as if they // were via `static_libs`. Thus we need to alias the BuildRlibVariant // to "static" for Rust FFI libraries. - mctx.CreateAliasVariation("static", "") + return "" + } + if incomingVariation != "" { + return incomingVariation + } + if buildShared { + return "shared" + } else if buildStatic { + return "static" + } + return "" + } + return "" +} + +func (linkageTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + ccPrebuilt := false + if m, ok := ctx.Module().(*Module); ok && m.linker != nil { + _, ccPrebuilt = m.linker.(prebuiltLibraryInterface) + } + if ccPrebuilt { + library := ctx.Module().(*Module).linker.(prebuiltLibraryInterface) + if variation == "static" { + library.setStatic() + if !library.buildStatic() { + library.disablePrebuilt() + } + } else if variation == "shared" { + library.setShared() + if !library.buildShared() { + library.disablePrebuilt() + } + } + } else if library, ok := ctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() { + if variation == "static" { + library.SetStatic() + } else if variation == "shared" { + library.SetShared() + var isLLNDK bool + if m, ok := ctx.Module().(*Module); ok { + isLLNDK = m.IsLlndk() + } + buildStatic := library.BuildStaticVariant() && !isLLNDK + buildShared := library.BuildSharedVariant() + if buildStatic && buildShared { + if _, ok := library.(*Module); ok { + reuseStaticLibrary(ctx, library.(*Module)) + } + } } } } @@ -2204,64 +2250,14 @@ func normalizeVersions(ctx android.BaseModuleContext, versions []string) { } } -func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) { - // "" is for the non-stubs (implementation) variant for system modules, or the LLNDK variant - // for LLNDK modules. - variants := append(android.CopyOf(versions), "") - - m := mctx.Module().(*Module) - isLLNDK := m.IsLlndk() - isVendorPublicLibrary := m.IsVendorPublicLibrary() - isImportedApiLibrary := m.isImportedApiLibrary() - - modules := mctx.CreateLocalVariations(variants...) - for i, m := range modules { - - if variants[i] != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary { - // A stubs or LLNDK stubs variant. - c := m.(*Module) - if c.sanitize != nil { - c.sanitize.Properties.ForceDisable = true - } - if c.stl != nil { - c.stl.Properties.Stl = StringPtr("none") - } - c.Properties.PreventInstall = true - lib := moduleLibraryInterface(m) - isLatest := i == (len(versions) - 1) - lib.setBuildStubs(isLatest) - - if variants[i] != "" { - // A non-LLNDK stubs module is hidden from make and has a dependency from the - // implementation module to the stubs module. - c.Properties.HideFromMake = true - lib.setStubsVersion(variants[i]) - mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i]) - } - } - } - mctx.AliasVariation("") - latestVersion := "" - if len(versions) > 0 { - latestVersion = versions[len(versions)-1] - } - mctx.CreateAliasVariation("latest", latestVersion) -} - -func createPerApiVersionVariations(mctx android.BottomUpMutatorContext, minSdkVersion string) { +func perApiVersionVariations(mctx android.BaseModuleContext, minSdkVersion string) []string { from, err := nativeApiLevelFromUser(mctx, minSdkVersion) if err != nil { mctx.PropertyErrorf("min_sdk_version", err.Error()) - return + return []string{""} } - versionStrs := ndkLibraryVersions(mctx, from) - modules := mctx.CreateLocalVariations(versionStrs...) - - for i, module := range modules { - module.(*Module).Properties.Sdk_version = StringPtr(versionStrs[i]) - module.(*Module).Properties.Min_sdk_version = StringPtr(versionStrs[i]) - } + return ndkLibraryVersions(mctx, from) } func canBeOrLinkAgainstVersionVariants(module interface { @@ -2291,7 +2287,7 @@ func moduleLibraryInterface(module blueprint.Module) libraryInterface { } // setStubsVersions normalizes the versions in the Stubs.Versions property into MutatedProperties.AllStubsVersions. -func setStubsVersions(mctx android.BottomUpMutatorContext, library libraryInterface, module *Module) { +func setStubsVersions(mctx android.BaseModuleContext, library libraryInterface, module *Module) { if !library.buildShared() || !canBeVersionVariant(module) { return } @@ -2304,25 +2300,98 @@ func setStubsVersions(mctx android.BottomUpMutatorContext, library libraryInterf library.setAllStubsVersions(versions) } -// versionMutator splits a module into the mandatory non-stubs variant +// versionTransitionMutator splits a module into the mandatory non-stubs variant // (which is unnamed) and zero or more stubs variants. -func versionMutator(mctx android.BottomUpMutatorContext) { - if mctx.Os() != android.Android { - return +type versionTransitionMutator struct{} + +func (versionTransitionMutator) Split(ctx android.BaseModuleContext) []string { + if ctx.Os() != android.Android { + return []string{""} + } + + m, ok := ctx.Module().(*Module) + if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) { + setStubsVersions(ctx, library, m) + + return append(slices.Clone(library.allStubsVersions()), "") + } else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() { + return perApiVersionVariations(ctx, m.MinSdkVersion()) + } + + return []string{""} +} + +func (versionTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + return "" +} + +func (versionTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if ctx.Os() != android.Android { + return "" + } + m, ok := ctx.Module().(*Module) + if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) { + if incomingVariation == "latest" { + latestVersion := "" + versions := library.allStubsVersions() + if len(versions) > 0 { + latestVersion = versions[len(versions)-1] + } + return latestVersion + } + return incomingVariation + } else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() { + // If this module only has variants with versions and the incoming dependency doesn't specify which one + // is needed then assume the latest version. + if incomingVariation == "" { + return android.FutureApiLevel.String() + } + return incomingVariation } - m, ok := mctx.Module().(*Module) - if library := moduleLibraryInterface(mctx.Module()); library != nil && canBeVersionVariant(m) { - setStubsVersions(mctx, library, m) + return "" +} - createVersionVariations(mctx, library.allStubsVersions()) +func (versionTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + // Optimization: return early if this module can't be affected. + if ctx.Os() != android.Android { return } - if ok { - if m.SplitPerApiLevel() && m.IsSdkVariant() { - createPerApiVersionVariations(mctx, m.MinSdkVersion()) + m, ok := ctx.Module().(*Module) + if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) { + isLLNDK := m.IsLlndk() + isVendorPublicLibrary := m.IsVendorPublicLibrary() + isImportedApiLibrary := m.isImportedApiLibrary() + + if variation != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary { + // A stubs or LLNDK stubs variant. + if m.sanitize != nil { + m.sanitize.Properties.ForceDisable = true + } + if m.stl != nil { + m.stl.Properties.Stl = StringPtr("none") + } + m.Properties.PreventInstall = true + lib := moduleLibraryInterface(m) + allStubsVersions := library.allStubsVersions() + isLatest := len(allStubsVersions) > 0 && variation == allStubsVersions[len(allStubsVersions)-1] + lib.setBuildStubs(isLatest) + } + if variation != "" { + // A non-LLNDK stubs module is hidden from make + library.setStubsVersion(variation) + m.Properties.HideFromMake = true + } else { + // A non-LLNDK implementation module has a dependency to all stubs versions + for _, version := range library.allStubsVersions() { + ctx.AddVariationDependencies([]blueprint.Variation{{"version", version}}, + stubImplDepTag, ctx.ModuleName()) + } } + } else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() { + m.Properties.Sdk_version = StringPtr(variation) + m.Properties.Min_sdk_version = StringPtr(variation) } } diff --git a/cc/library_stub.go b/cc/library_stub.go index 6f06333ac..636782581 100644 --- a/cc/library_stub.go +++ b/cc/library_stub.go @@ -303,7 +303,7 @@ func (d *apiLibraryDecorator) hasStubsVariants() bool { return d.hasApexStubs() } -func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string { +func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseModuleContext) []string { m, ok := ctx.Module().(*Module) if !ok { diff --git a/cc/ndk_library.go b/cc/ndk_library.go index f32606814..b822e5cbb 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -133,7 +133,7 @@ func (stub *stubDecorator) implementationModuleName(name string) string { return strings.TrimSuffix(name, ndkLibrarySuffix) } -func ndkLibraryVersions(ctx android.BaseMutatorContext, from android.ApiLevel) []string { +func ndkLibraryVersions(ctx android.BaseModuleContext, from android.ApiLevel) []string { var versions []android.ApiLevel versionStrs := []string{} for _, version := range ctx.Config().AllSupportedApiLevels() { @@ -147,7 +147,7 @@ func ndkLibraryVersions(ctx android.BaseMutatorContext, from android.ApiLevel) [ return versionStrs } -func (this *stubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string { +func (this *stubDecorator) stubsVersions(ctx android.BaseModuleContext) []string { if !ctx.Module().Enabled(ctx) { return nil } @@ -19,73 +19,133 @@ import ( "android/soong/genrule" ) -// sdkMutator sets a creates a platform and an SDK variant for modules +// sdkTransitionMutator creates a platform and an SDK variant for modules // that set sdk_version, and ignores sdk_version for the platform // variant. The SDK variant will be used for embedding in APKs // that may be installed on older platforms. Apexes use their own // variants that enforce backwards compatibility. -func sdkMutator(ctx android.BottomUpMutatorContext) { +type sdkTransitionMutator struct{} + +func (sdkTransitionMutator) Split(ctx android.BaseModuleContext) []string { if ctx.Os() != android.Android { - return + return []string{""} } 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?") } - modules := ctx.CreateVariations("sdk") - modules[0].(*Module).Properties.IsSdkVariant = true + return []string{"sdk"} } else if m.UseSdk() || m.SplitPerApiLevel() { - modules := ctx.CreateVariations("", "sdk") - - // Clear the sdk_version property for the platform (non-SDK) variant so later code - // doesn't get confused by it. - modules[0].(*Module).Properties.Sdk_version = nil - - // Mark the SDK variant. - modules[1].(*Module).Properties.IsSdkVariant = true - - if ctx.Config().UnbundledBuildApps() { - // For an unbundled apps build, hide the platform variant from Make - // so that other Make modules don't link against it, but against the - // SDK variant. - modules[0].(*Module).Properties.HideFromMake = true + return []string{"", "sdk"} + } else { + return []string{""} + } + case *genrule.Module: + if p, ok := m.Extra.(*GenruleExtraProperties); ok { + if String(p.Sdk_version) != "" { + return []string{"", "sdk"} } 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 + return []string{""} } - // SDK variant never gets installed because the variant is to be embedded in - // APKs, not to be installed to the platform. - modules[1].(*Module).Properties.PreventInstall = true - ctx.AliasVariation("") + } + case *CcApiVariant: + ccApiVariant, _ := ctx.Module().(*CcApiVariant) + if String(ccApiVariant.properties.Variant) == "ndk" { + return []string{"sdk"} } 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. - ccModule.Properties.Sdk_version = nil - } - ctx.CreateVariations("") - ctx.AliasVariation("") + return []string{""} + } + } + + return []string{""} +} + +func (sdkTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + return sourceVariation +} + +func (sdkTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if ctx.Os() != android.Android { + return "" + } + switch m := ctx.Module().(type) { + case LinkableInterface: + if m.AlwaysSdk() { + return "sdk" + } else if m.UseSdk() || m.SplitPerApiLevel() { + return incomingVariation } case *genrule.Module: if p, ok := m.Extra.(*GenruleExtraProperties); ok { if String(p.Sdk_version) != "" { - ctx.CreateVariations("", "sdk") - } else { - ctx.CreateVariations("") + return incomingVariation } - ctx.AliasVariation("") } case *CcApiVariant: ccApiVariant, _ := ctx.Module().(*CcApiVariant) if String(ccApiVariant.properties.Variant) == "ndk" { - ctx.CreateVariations("sdk") + return "sdk" + } + } + + if ctx.IsAddingDependency() { + return incomingVariation + } else { + return "" + } +} + +func (sdkTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + if ctx.Os() != android.Android { + return + } + + switch m := ctx.Module().(type) { + case LinkableInterface: + ccModule, isCcModule := ctx.Module().(*Module) + if m.AlwaysSdk() { + if variation != "sdk" { + ctx.ModuleErrorf("tried to create variation %q for module with AlwaysSdk set, expected \"sdk\"", variation) + } + + ccModule.Properties.IsSdkVariant = true + } else if m.UseSdk() || m.SplitPerApiLevel() { + if variation == "" { + // Clear the sdk_version property for the platform (non-SDK) variant so later code + // doesn't get confused by it. + ccModule.Properties.Sdk_version = nil + } else { + // Mark the SDK variant. + ccModule.Properties.IsSdkVariant = true + + // SDK variant never gets installed because the variant is to be embedded in + // APKs, not to be installed to the platform. + ccModule.Properties.PreventInstall = true + } + + if ctx.Config().UnbundledBuildApps() { + if variation == "" { + // For an unbundled apps build, hide the platform variant from Make + // so that other Make modules don't link against it, but against the + // SDK variant. + ccModule.Properties.HideFromMake = true + } + } else { + if variation == "sdk" { + // For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when + // exposed to Make. + ccModule.Properties.SdkAndPlatformVariantVisibleToMake = true + } + } } else { - ctx.CreateVariations("") + 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. + ccModule.Properties.Sdk_version = nil + } } } } |