diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go index db3313d27..fb03c2324 100644 --- a/androidmk/parser/parser_test.go +++ b/androidmk/parser/parser_test.go @@ -86,20 +86,19 @@ endif`, }, { name: "Blank line in rule's command", - in: `all: + in: `all: echo first line echo second line`, out: []Node{ &Rule{ - Target: SimpleMakeString("all", NoPos), - RecipePos: NoPos, - Recipe: "echo first line\necho second line", + Target: SimpleMakeString("all", NoPos), + RecipePos: NoPos, + Recipe: "echo first line\necho second line", Prerequisites: SimpleMakeString("", NoPos), }, }, }, - } func TestParse(t *testing.T) { diff --git a/apex/apex.go b/apex/apex.go index f9b30d4b6..5a75d3e49 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -703,7 +703,6 @@ func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeM rustLibVariations := append( target.Variations(), []blueprint.Variation{ {Mutator: "rust_libraries", Variation: "dylib"}, - {Mutator: "link", Variation: ""}, }..., ) diff --git a/cc/cc.go b/cc/cc.go index d307be615..64b24654e 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -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() }) 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...) - - modules := mctx.CreateLocalVariations(variations...) - modules[0].(LinkableInterface).SetShared() - mctx.AliasVariation("shared") - } else if len(variations) > 0 { - mctx.CreateLocalVariations(variations...) - mctx.AliasVariation(variations[0]) + variations = append([]string{"shared"}, variations...) } - if library.BuildRlibVariant() && library.IsRustFFI() && !buildStatic { + + if len(variations) > 0 { + return variations + } + } + return []string{""} +} + +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 + } + 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 := mctx.Module().(*Module) - if library := moduleLibraryInterface(mctx.Module()); library != nil && canBeVersionVariant(m) { - setStubsVersions(mctx, library, m) + m, ok := ctx.Module().(*Module) + if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) { + setStubsVersions(ctx, library, m) - createVersionVariations(mctx, library.allStubsVersions()) - return + return append(slices.Clone(library.allStubsVersions()), "") + } else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() { + return perApiVersionVariations(ctx, m.MinSdkVersion()) } - if ok { - if m.SplitPerApiLevel() && m.IsSdkVariant() { - createPerApiVersionVariations(mctx, 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 + } + + return "" +} + +func (versionTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + // Optimization: return early if this module can't be affected. + if ctx.Os() != android.Android { + return + } + + 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 } diff --git a/cc/sdk.go b/cc/sdk.go index 4925ce166..dc1261d68 100644 --- a/cc/sdk.go +++ b/cc/sdk.go @@ -19,12 +19,86 @@ 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 []string{""} + } + + switch m := ctx.Module().(type) { + case LinkableInterface: + 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?") + } + return []string{"sdk"} + } else if m.UseSdk() || m.SplitPerApiLevel() { + 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 { + return []string{""} + } + } + case *CcApiVariant: + ccApiVariant, _ := ctx.Module().(*CcApiVariant) + if String(ccApiVariant.properties.Variant) == "ndk" { + return []string{"sdk"} + } else { + 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) != "" { + return incomingVariation + } + } + case *CcApiVariant: + ccApiVariant, _ := ctx.Module().(*CcApiVariant) + if String(ccApiVariant.properties.Variant) == "ndk" { + return "sdk" + } + } + + if ctx.IsAddingDependency() { + return incomingVariation + } else { + return "" + } +} + +func (sdkTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { if ctx.Os() != android.Android { return } @@ -33,59 +107,45 @@ func sdkMutator(ctx android.BottomUpMutatorContext) { 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?") + if variation != "sdk" { + ctx.ModuleErrorf("tried to create variation %q for module with AlwaysSdk set, expected \"sdk\"", variation) } - modules := ctx.CreateVariations("sdk") - modules[0].(*Module).Properties.IsSdkVariant = true + + ccModule.Properties.IsSdkVariant = true } else if m.UseSdk() || m.SplitPerApiLevel() { - modules := ctx.CreateVariations("", "sdk") + 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 - // 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 + // 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() { - // 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 + 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 { - // 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 + 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 + } } - // 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("") } 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("") - } - case *genrule.Module: - if p, ok := m.Extra.(*GenruleExtraProperties); ok { - if String(p.Sdk_version) != "" { - ctx.CreateVariations("", "sdk") - } else { - ctx.CreateVariations("") - } - ctx.AliasVariation("") - } - case *CcApiVariant: - ccApiVariant, _ := ctx.Module().(*CcApiVariant) - if String(ccApiVariant.properties.Variant) == "ndk" { - ctx.CreateVariations("sdk") - } else { - ctx.CreateVariations("") } } } diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 201515f51..b69a76fc2 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -532,7 +532,7 @@ func OdexOnSystemOtherByName(name string, dexLocation string, global *GlobalConf } for _, f := range global.PatternsOnSystemOther { - if makefileMatch("/" + f, dexLocation) || makefileMatch(filepath.Join(SystemPartition, f), dexLocation) { + if makefileMatch("/"+f, dexLocation) || makefileMatch(filepath.Join(SystemPartition, f), dexLocation) { return true } } diff --git a/python/python.go b/python/python.go index 1ee533fa8..8726f02ef 100644 --- a/python/python.go +++ b/python/python.go @@ -38,7 +38,7 @@ func registerPythonMutators(ctx android.RegistrationContext) { // Exported to support other packages using Python modules in tests. func RegisterPythonPreDepsMutators(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("python_version", versionSplitMutator()).Parallel() + ctx.Transition("python_version", &versionSplitTransitionMutator{}) } // the version-specific properties that apply to python modules. @@ -245,7 +245,6 @@ var ( protoExt = ".proto" pyVersion2 = "PY2" pyVersion3 = "PY3" - pyVersion2And3 = "PY2ANDPY3" internalPath = "internal" ) @@ -253,46 +252,68 @@ type basePropertiesProvider interface { getBaseProperties() *BaseProperties } -// versionSplitMutator creates version variants for modules and appends the version-specific -// properties for a given variant to the properties in the variant module -func versionSplitMutator() func(android.BottomUpMutatorContext) { - return func(mctx android.BottomUpMutatorContext) { - if base, ok := mctx.Module().(basePropertiesProvider); ok { - props := base.getBaseProperties() - var versionNames []string - // collect version specific properties, so that we can merge version-specific properties - // into the module's overall properties - var versionProps []VersionProperties - // PY3 is first so that we alias the PY3 variant rather than PY2 if both - // are available - if proptools.BoolDefault(props.Version.Py3.Enabled, true) { - versionNames = append(versionNames, pyVersion3) - versionProps = append(versionProps, props.Version.Py3) - } - if proptools.BoolDefault(props.Version.Py2.Enabled, false) { - if !mctx.DeviceConfig().BuildBrokenUsesSoongPython2Modules() && - mctx.ModuleName() != "py2-cmd" && - mctx.ModuleName() != "py2-stdlib" { - mctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3. This error can be temporarily overridden by setting BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES := true in the product configuration") - } - versionNames = append(versionNames, pyVersion2) - versionProps = append(versionProps, props.Version.Py2) - } - modules := mctx.CreateLocalVariations(versionNames...) - // Alias module to the first variant - if len(versionNames) > 0 { - mctx.AliasVariation(versionNames[0]) - } - for i, v := range versionNames { - // set the actual version for Python module. - newProps := modules[i].(basePropertiesProvider).getBaseProperties() - newProps.Actual_version = v - // append versioned properties for the Python module to the overall properties - err := proptools.AppendMatchingProperties([]interface{}{newProps}, &versionProps[i], nil) - if err != nil { - panic(err) - } +type versionSplitTransitionMutator struct{} + +func (versionSplitTransitionMutator) Split(ctx android.BaseModuleContext) []string { + if base, ok := ctx.Module().(basePropertiesProvider); ok { + props := base.getBaseProperties() + var variants []string + // PY3 is first so that we alias the PY3 variant rather than PY2 if both + // are available + if proptools.BoolDefault(props.Version.Py3.Enabled, true) { + variants = append(variants, pyVersion3) + } + if proptools.BoolDefault(props.Version.Py2.Enabled, false) { + if !ctx.DeviceConfig().BuildBrokenUsesSoongPython2Modules() && + ctx.ModuleName() != "py2-cmd" && + ctx.ModuleName() != "py2-stdlib" { + ctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3. This error can be temporarily overridden by setting BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES := true in the product configuration") } + variants = append(variants, pyVersion2) + } + return variants + } + return []string{""} +} + +func (versionSplitTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + return "" +} + +func (versionSplitTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if incomingVariation != "" { + return incomingVariation + } + if base, ok := ctx.Module().(basePropertiesProvider); ok { + props := base.getBaseProperties() + if proptools.BoolDefault(props.Version.Py3.Enabled, true) { + return pyVersion3 + } else { + return pyVersion2 + } + } + + return "" +} + +func (versionSplitTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + if variation == "" { + return + } + if base, ok := ctx.Module().(basePropertiesProvider); ok { + props := base.getBaseProperties() + props.Actual_version = variation + + var versionProps *VersionProperties + if variation == pyVersion3 { + versionProps = &props.Version.Py3 + } else if variation == pyVersion2 { + versionProps = &props.Version.Py2 + } + + err := proptools.AppendMatchingProperties([]interface{}{props}, versionProps, nil) + if err != nil { + panic(err) } } } diff --git a/rust/coverage.go b/rust/coverage.go index e0e919c69..91a78060d 100644 --- a/rust/coverage.go +++ b/rust/coverage.go @@ -47,7 +47,7 @@ func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps { // no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency. if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() { - ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}, rlibDepTag, ProfilerBuiltins) + ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, ProfilerBuiltins) } } diff --git a/rust/library.go b/rust/library.go index ba73f27fd..50d5a72ae 100644 --- a/rust/library.go +++ b/rust/library.go @@ -20,6 +20,8 @@ import ( "regexp" "strings" + "github.com/google/blueprint" + "android/soong/android" "android/soong/cc" ) @@ -692,31 +694,28 @@ func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name stri } } -// LibraryMutator mutates the libraries into variants according to the -// build{Rlib,Dylib} attributes. -func LibraryMutator(mctx android.BottomUpMutatorContext) { - // Only mutate on Rust libraries. - m, ok := mctx.Module().(*Module) +type libraryTransitionMutator struct{} + +func (libraryTransitionMutator) Split(ctx android.BaseModuleContext) []string { + m, ok := ctx.Module().(*Module) if !ok || m.compiler == nil { - return + return []string{""} } library, ok := m.compiler.(libraryInterface) if !ok { - return + return []string{""} } // Don't produce rlib/dylib/source variants for shared or static variants if library.shared() || library.static() { - return + return []string{""} } var variants []string // The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib) // depend on this variant. It must be the first variant to be declared. - sourceVariant := false if m.sourceProvider != nil { - variants = append(variants, "source") - sourceVariant = true + variants = append(variants, sourceVariation) } if library.buildRlib() { variants = append(variants, rlibVariation) @@ -726,92 +725,134 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { } if len(variants) == 0 { - return + return []string{""} } - modules := mctx.CreateLocalVariations(variants...) - // The order of the variations (modules) matches the variant names provided. Iterate - // through the new variation modules and set their mutated properties. - var emptyVariant = false - var rlibVariant = false - for i, v := range modules { - switch variants[i] { - case rlibVariation: - v.(*Module).compiler.(libraryInterface).setRlib() - rlibVariant = true - case dylibVariation: - v.(*Module).compiler.(libraryInterface).setDylib() - if v.(*Module).ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { - // TODO(b/165791368) - // Disable dylib Vendor Ramdisk variations until we support these. - v.(*Module).Disable() - } + return variants +} - case "source": - v.(*Module).compiler.(libraryInterface).setSource() - // The source variant does not produce any library. - // Disable the compilation steps. - v.(*Module).compiler.SetDisabled() - case "": - emptyVariant = true +func (libraryTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + return "" +} + +func (libraryTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + m, ok := ctx.Module().(*Module) + if !ok || m.compiler == nil { + return "" + } + library, ok := m.compiler.(libraryInterface) + if !ok { + return "" + } + + if incomingVariation == "" { + if m.sourceProvider != nil { + return sourceVariation + } + if library.shared() { + return "" + } + if library.buildRlib() { + return rlibVariation + } + if library.buildDylib() { + return dylibVariation } } + return incomingVariation +} - if rlibVariant && library.isFFILibrary() { - // If an rlib variant is set and this is an FFI library, make it the - // default variant so CC can link against it appropriately. - mctx.AliasVariation(rlibVariation) - } else if emptyVariant { - // If there's an empty variant, alias it so it is the default variant - mctx.AliasVariation("") +func (libraryTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + m, ok := ctx.Module().(*Module) + if !ok || m.compiler == nil { + return + } + library, ok := m.compiler.(libraryInterface) + if !ok { + return + } + + switch variation { + case rlibVariation: + library.setRlib() + case dylibVariation: + library.setDylib() + if m.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { + // TODO(b/165791368) + // Disable dylib Vendor Ramdisk variations until we support these. + m.Disable() + } + + case sourceVariation: + library.setSource() + // The source variant does not produce any library. + // Disable the compilation steps. + m.compiler.SetDisabled() } // If a source variant is created, add an inter-variant dependency // between the other variants and the source variant. - if sourceVariant { - sv := modules[0] - for _, v := range modules[1:] { - if !v.Enabled(mctx) { - continue - } - mctx.AddInterVariantDependency(sourceDepTag, v, sv) - } - // Alias the source variation so it can be named directly in "srcs" properties. - mctx.AliasVariation("source") + if m.sourceProvider != nil && variation != sourceVariation { + ctx.AddVariationDependencies( + []blueprint.Variation{ + {"rust_libraries", sourceVariation}, + }, + sourceDepTag, ctx.ModuleName()) } } -func LibstdMutator(mctx android.BottomUpMutatorContext) { - if m, ok := mctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { - switch library := m.compiler.(type) { - case libraryInterface: - // Only create a variant if a library is actually being built. - if library.rlib() && !library.sysroot() { - // If this is a rust_ffi variant it only needs rlib-std - if library.isFFILibrary() { - variants := []string{"rlib-std"} - modules := mctx.CreateLocalVariations(variants...) - rlib := modules[0].(*Module) - rlib.compiler.(libraryInterface).setRlibStd() - rlib.Properties.RustSubName += RlibStdlibSuffix - mctx.AliasVariation("rlib-std") - } else { - variants := []string{"rlib-std", "dylib-std"} - modules := mctx.CreateLocalVariations(variants...) +type libstdTransitionMutator struct{} - rlib := modules[0].(*Module) - dylib := modules[1].(*Module) - rlib.compiler.(libraryInterface).setRlibStd() - dylib.compiler.(libraryInterface).setDylibStd() - if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { - // TODO(b/165791368) - // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib - // variants are properly supported. - dylib.Disable() - } - rlib.Properties.RustSubName += RlibStdlibSuffix +func (libstdTransitionMutator) Split(ctx android.BaseModuleContext) []string { + if m, ok := ctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { + // Only create a variant if a library is actually being built. + if library, ok := m.compiler.(libraryInterface); ok { + if library.rlib() && !library.sysroot() { + if library.isFFILibrary() { + return []string{"rlib-std"} + } else { + return []string{"rlib-std", "dylib-std"} } } } } + return []string{""} +} + +func (libstdTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + return "" +} + +func (libstdTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if m, ok := ctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { + if library, ok := m.compiler.(libraryInterface); ok { + if library.shared() { + return "" + } + if library.rlib() && !library.sysroot() { + if incomingVariation != "" { + return incomingVariation + } + return "rlib-std" + } + } + } + return "" +} + +func (libstdTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + if variation == "rlib-std" { + rlib := ctx.Module().(*Module) + rlib.compiler.(libraryInterface).setRlibStd() + rlib.Properties.RustSubName += RlibStdlibSuffix + } else if variation == "dylib-std" { + dylib := ctx.Module().(*Module) + dylib.compiler.(libraryInterface).setDylibStd() + if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { + // TODO(b/165791368) + // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib + // variants are properly supported. + dylib.Disable() + } + } } diff --git a/rust/rust.go b/rust/rust.go index 9dae75ee5..3402adcc5 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -37,20 +37,24 @@ var pctx = android.NewPackageContext("android/soong/rust") func init() { android.RegisterModuleType("rust_defaults", defaultsFactory) - android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() - ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel() - ctx.BottomUp("rust_begin", BeginMutator).Parallel() - }) - android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() - }) + android.PreDepsMutators(registerPreDepsMutators) + android.PostDepsMutators(registerPostDepsMutators) pctx.Import("android/soong/android") pctx.Import("android/soong/rust/config") pctx.ImportAs("cc_config", "android/soong/cc/config") android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory) } +func registerPreDepsMutators(ctx android.RegisterMutatorsContext) { + ctx.Transition("rust_libraries", &libraryTransitionMutator{}) + ctx.Transition("rust_stdlinkage", &libstdTransitionMutator{}) + ctx.BottomUp("rust_begin", BeginMutator).Parallel() +} + +func registerPostDepsMutators(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() +} + type Flags struct { GlobalRustFlags []string // Flags that apply globally to rust GlobalLinkFlags []string // Flags that apply globally to linker @@ -1128,10 +1132,11 @@ type autoDep struct { } var ( - rlibVariation = "rlib" - dylibVariation = "dylib" - rlibAutoDep = autoDep{variation: rlibVariation, depTag: rlibDepTag} - dylibAutoDep = autoDep{variation: dylibVariation, depTag: dylibDepTag} + sourceVariation = "source" + rlibVariation = "rlib" + dylibVariation = "dylib" + rlibAutoDep = autoDep{variation: rlibVariation, depTag: rlibDepTag} + dylibAutoDep = autoDep{variation: dylibVariation, depTag: dylibDepTag} ) type autoDeppable interface { @@ -1613,7 +1618,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { } rlibDepVariations := commonDepVariations - rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""}) if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() { rlibDepVariations = append(rlibDepVariations, @@ -1629,7 +1633,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { // dylibs dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation}) - dylibDepVariations = append(dylibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""}) for _, lib := range deps.Dylibs { actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib) @@ -1650,7 +1653,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { // otherwise select the rlib variant. autoDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}) - autoDepVariations = append(autoDepVariations, blueprint.Variation{Mutator: "link", Variation: ""}) if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) { actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib) @@ -1664,8 +1666,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { } else if _, ok := mod.sourceProvider.(*protobufDecorator); ok { for _, lib := range deps.Rustlibs { srcProviderVariations := append(commonDepVariations, - blueprint.Variation{Mutator: "rust_libraries", Variation: "source"}) - srcProviderVariations = append(srcProviderVariations, blueprint.Variation{Mutator: "link", Variation: ""}) + blueprint.Variation{Mutator: "rust_libraries", Variation: sourceVariation}) // Only add rustlib dependencies if they're source providers themselves. // This is used to track which crate names need to be added to the source generated @@ -1681,7 +1682,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { if deps.Stdlibs != nil { if mod.compiler.stdLinkage(ctx) == RlibLinkage { for _, lib := range deps.Stdlibs { - actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}...), + actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...), rlibDepTag, lib) } } else { diff --git a/rust/rust_test.go b/rust/rust_test.go index 0d005d0a2..eeedf3f57 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -60,6 +60,7 @@ var rustMockedFiles = android.MockFS{ // testRust returns a TestContext in which a basic environment has been setup. // This environment contains a few mocked files. See rustMockedFiles for the list of these files. func testRust(t *testing.T, bp string) *android.TestContext { + t.Helper() skipTestIfOsNotSupported(t) result := android.GroupFixturePreparers( prepareForRustTest, diff --git a/rust/testing.go b/rust/testing.go index 6ee49a971..32cc82354 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -200,15 +200,8 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.RegisterModuleType("rust_prebuilt_library", PrebuiltLibraryFactory) ctx.RegisterModuleType("rust_prebuilt_dylib", PrebuiltDylibFactory) ctx.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory) - ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { - // rust mutators - ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() - ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel() - ctx.BottomUp("rust_begin", BeginMutator).Parallel() - }) + ctx.PreDepsMutators(registerPreDepsMutators) ctx.RegisterParallelSingletonType("rust_project_generator", rustProjectGeneratorSingleton) ctx.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory) - ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() - }) + ctx.PostDepsMutators(registerPostDepsMutators) } diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go index 81c678d3f..6c9a1ebb9 100644 --- a/ui/build/paths/config.go +++ b/ui/build/paths/config.go @@ -86,28 +86,28 @@ func GetConfig(name string) PathConfig { // This list specifies whether a particular binary from $PATH is allowed to be // run during the build. For more documentation, see path_interposer.go . var Configuration = map[string]PathConfig{ - "bash": Allowed, - "diff": Allowed, - "dlv": Allowed, - "expr": Allowed, - "fuser": Allowed, - "gcert": Allowed, - "gcertstatus": Allowed, - "gcloud": Allowed, - "git": Allowed, - "hexdump": Allowed, - "jar": Allowed, - "java": Allowed, - "javap": Allowed, - "lsof": Allowed, - "openssl": Allowed, - "pstree": Allowed, - "rsync": Allowed, - "sh": Allowed, - "stubby": Allowed, - "tr": Allowed, - "unzip": Allowed, - "zip": Allowed, + "bash": Allowed, + "diff": Allowed, + "dlv": Allowed, + "expr": Allowed, + "fuser": Allowed, + "gcert": Allowed, + "gcertstatus": Allowed, + "gcloud": Allowed, + "git": Allowed, + "hexdump": Allowed, + "jar": Allowed, + "java": Allowed, + "javap": Allowed, + "lsof": Allowed, + "openssl": Allowed, + "pstree": Allowed, + "rsync": Allowed, + "sh": Allowed, + "stubby": Allowed, + "tr": Allowed, + "unzip": Allowed, + "zip": Allowed, // Host toolchain is removed. In-tree toolchain should be used instead. // GCC also can't find cc1 with this implementation.