diff options
34 files changed, 678 insertions, 201 deletions
diff --git a/Android.bp b/Android.bp index f425c3f3f..2a4653a13 100644 --- a/Android.bp +++ b/Android.bp @@ -204,6 +204,7 @@ bootstrap_go_package { "cc/linker.go", "cc/binary.go", + "cc/binary_sdk_member.go", "cc/fuzz.go", "cc/library.go", "cc/library_sdk_member.go", diff --git a/android/apex.go b/android/apex.go index 17ec9b195..43a42df9b 100644 --- a/android/apex.go +++ b/android/apex.go @@ -19,6 +19,14 @@ import ( "sync" ) +type ApexInfo struct { + // Name of the apex variant that this module is mutated into + ApexName string + + // Whether this apex variant needs to target Android 10 + LegacyAndroid10Support bool +} + // ApexModule is the interface that a module type is expected to implement if // the module has to be built differently depending on whether the module // is destined for an apex or not (installed to one of the regular partitions). @@ -38,12 +46,12 @@ type ApexModule interface { Module apexModuleBase() *ApexModuleBase - // Marks that this module should be built for the APEXes of the specified names. + // Marks that this module should be built for the specified APEXes. // Call this before apex.apexMutator is run. - BuildForApexes(apexNames []string) + BuildForApexes(apexes []ApexInfo) - // Returns the name of the APEXes that this modoule will be built for - ApexVariations() []string + // Returns the APEXes that this module will be built for + ApexVariations() []ApexInfo // Returns the name of APEX that this module will be built for. Empty string // is returned when 'IsForPlatform() == true'. Note that a module can be @@ -72,10 +80,6 @@ type ApexModule interface { // for an APEX marked via BuildForApexes(). CreateApexVariations(mctx BottomUpMutatorContext) []Module - // Sets the name of the apex variant of this module. Called inside - // CreateApexVariations. - setApexName(apexName string) - // Tests if this module is available for the specified APEX or ":platform" AvailableFor(what string) bool @@ -94,8 +98,7 @@ type ApexProperties struct { // Default is ["//apex_available:platform"]. Apex_available []string - // Name of the apex variant that this module is mutated into - ApexName string `blueprint:"mutated"` + Info ApexInfo `blueprint:"mutated"` } // Provides default implementation for the ApexModule interface. APEX-aware @@ -106,37 +109,37 @@ type ApexModuleBase struct { canHaveApexVariants bool apexVariationsLock sync.Mutex // protects apexVariations during parallel apexDepsMutator - apexVariations []string + apexVariations []ApexInfo } func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase { return m } -func (m *ApexModuleBase) BuildForApexes(apexNames []string) { +func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) { m.apexVariationsLock.Lock() defer m.apexVariationsLock.Unlock() - for _, apexName := range apexNames { - if !InList(apexName, m.apexVariations) { - m.apexVariations = append(m.apexVariations, apexName) +nextApex: + for _, apex := range apexes { + for _, v := range m.apexVariations { + if v.ApexName == apex.ApexName { + continue nextApex + } } + m.apexVariations = append(m.apexVariations, apex) } } -func (m *ApexModuleBase) ApexVariations() []string { +func (m *ApexModuleBase) ApexVariations() []ApexInfo { return m.apexVariations } func (m *ApexModuleBase) ApexName() string { - return m.ApexProperties.ApexName + return m.ApexProperties.Info.ApexName } func (m *ApexModuleBase) IsForPlatform() bool { - return m.ApexProperties.ApexName == "" -} - -func (m *ApexModuleBase) setApexName(apexName string) { - m.ApexProperties.ApexName = apexName + return m.ApexProperties.Info.ApexName == "" } func (m *ApexModuleBase) CanHaveApexVariants() bool { @@ -185,25 +188,35 @@ func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) { } } +type byApexName []ApexInfo + +func (a byApexName) Len() int { return len(a) } +func (a byApexName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byApexName) Less(i, j int) bool { return a[i].ApexName < a[j].ApexName } + func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module { if len(m.apexVariations) > 0 { m.checkApexAvailableProperty(mctx) - sort.Strings(m.apexVariations) + sort.Sort(byApexName(m.apexVariations)) variations := []string{} variations = append(variations, "") // Original variation for platform - variations = append(variations, m.apexVariations...) + for _, apex := range m.apexVariations { + variations = append(variations, apex.ApexName) + } defaultVariation := "" mctx.SetDefaultDependencyVariation(&defaultVariation) modules := mctx.CreateVariations(variations...) - for i, m := range modules { + for i, mod := range modules { platformVariation := i == 0 - if platformVariation && !mctx.Host() && !m.(ApexModule).AvailableFor(AvailableToPlatform) { - m.SkipInstall() + if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) { + mod.SkipInstall() + } + if !platformVariation { + mod.(ApexModule).apexModuleBase().ApexProperties.Info = m.apexVariations[i-1] } - m.(ApexModule).setApexName(variations[i]) } return modules } @@ -230,16 +243,16 @@ func apexNamesMap() map[string]map[string]bool { // depended on by the specified APEXes. Directly depending means that a module // is explicitly listed in the build definition of the APEX via properties like // native_shared_libs, java_libs, etc. -func UpdateApexDependency(apexNames []string, moduleName string, directDep bool) { +func UpdateApexDependency(apexes []ApexInfo, moduleName string, directDep bool) { apexNamesMapMutex.Lock() defer apexNamesMapMutex.Unlock() - for _, apexName := range apexNames { + for _, apex := range apexes { apexesForModule, ok := apexNamesMap()[moduleName] if !ok { apexesForModule = make(map[string]bool) apexNamesMap()[moduleName] = apexesForModule } - apexesForModule[apexName] = apexesForModule[apexName] || directDep + apexesForModule[apex.ApexName] = apexesForModule[apex.ApexName] || directDep } } diff --git a/android/arch.go b/android/arch.go index fb1acccda..73a490d79 100644 --- a/android/arch.go +++ b/android/arch.go @@ -1521,12 +1521,7 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) { // hasArmAbi returns true if arch has at least one arm ABI func hasArmAbi(arch Arch) bool { - for _, abi := range arch.Abi { - if strings.HasPrefix(abi, "arm") { - return true - } - } - return false + return PrefixInList(arch.Abi, "arm") } // hasArmArch returns true if targets has at least non-native_bridge arm Android arch diff --git a/android/config.go b/android/config.go index 9cf9662a8..1fe6f058b 100644 --- a/android/config.go +++ b/android/config.go @@ -890,11 +890,7 @@ func (c *config) EnforceRROForModule(name string) bool { func (c *config) EnforceRROExcludedOverlay(path string) bool { excluded := c.productVariables.EnforceRROExcludedOverlays if excluded != nil { - for _, exclude := range excluded { - if strings.HasPrefix(path, exclude) { - return true - } - } + return HasAnyPrefix(path, excluded) } return false } @@ -1050,12 +1046,12 @@ func (c *deviceConfig) ClangCoverageEnabled() bool { func (c *deviceConfig) CoverageEnabledForPath(path string) bool { coverage := false if c.config.productVariables.CoveragePaths != nil { - if InList("*", c.config.productVariables.CoveragePaths) || PrefixInList(path, c.config.productVariables.CoveragePaths) { + if InList("*", c.config.productVariables.CoveragePaths) || HasAnyPrefix(path, c.config.productVariables.CoveragePaths) { coverage = true } } if coverage && c.config.productVariables.CoverageExcludePaths != nil { - if PrefixInList(path, c.config.productVariables.CoverageExcludePaths) { + if HasAnyPrefix(path, c.config.productVariables.CoverageExcludePaths) { coverage = false } } @@ -1128,21 +1124,21 @@ func (c *config) IntegerOverflowDisabledForPath(path string) bool { if c.productVariables.IntegerOverflowExcludePaths == nil { return false } - return PrefixInList(path, c.productVariables.IntegerOverflowExcludePaths) + return HasAnyPrefix(path, c.productVariables.IntegerOverflowExcludePaths) } func (c *config) CFIDisabledForPath(path string) bool { if c.productVariables.CFIExcludePaths == nil { return false } - return PrefixInList(path, c.productVariables.CFIExcludePaths) + return HasAnyPrefix(path, c.productVariables.CFIExcludePaths) } func (c *config) CFIEnabledForPath(path string) bool { if c.productVariables.CFIIncludePaths == nil { return false } - return PrefixInList(path, c.productVariables.CFIIncludePaths) + return HasAnyPrefix(path, c.productVariables.CFIIncludePaths) } func (c *config) VendorConfig(name string) VendorConfig { diff --git a/android/neverallow.go b/android/neverallow.go index 48581df71..0cb20296c 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -407,8 +407,8 @@ func (r *rule) String() string { } func (r *rule) appliesToPath(dir string) bool { - includePath := len(r.paths) == 0 || hasAnyPrefix(dir, r.paths) - excludePath := hasAnyPrefix(dir, r.unlessPaths) + includePath := len(r.paths) == 0 || HasAnyPrefix(dir, r.paths) + excludePath := HasAnyPrefix(dir, r.unlessPaths) return includePath && !excludePath } @@ -474,15 +474,6 @@ func fieldNamesForProperties(propertyNames string) []string { return names } -func hasAnyPrefix(s string, prefixes []string) bool { - for _, prefix := range prefixes { - if strings.HasPrefix(s, prefix) { - return true - } - } - return false -} - func hasAnyProperty(properties []interface{}, props []ruleProperty) bool { for _, v := range props { if hasProperty(properties, v) { diff --git a/android/util.go b/android/util.go index e985fc1f5..ade851eff 100644 --- a/android/util.go +++ b/android/util.go @@ -122,7 +122,7 @@ func InList(s string, list []string) bool { } // Returns true if the given string s is prefixed with any string in the given prefix list. -func PrefixInList(s string, prefixList []string) bool { +func HasAnyPrefix(s string, prefixList []string) bool { for _, prefix := range prefixList { if strings.HasPrefix(s, prefix) { return true @@ -132,7 +132,7 @@ func PrefixInList(s string, prefixList []string) bool { } // Returns true if any string in the given list has the given prefix. -func PrefixedStringInList(list []string, prefix string) bool { +func PrefixInList(list []string, prefix string) bool { for _, s := range list { if strings.HasPrefix(s, prefix) { return true diff --git a/android/util_test.go b/android/util_test.go index 90fefeede..1f9ca361c 100644 --- a/android/util_test.go +++ b/android/util_test.go @@ -252,7 +252,7 @@ func TestPrefixInList(t *testing.T) { for _, testCase := range testcases { t.Run(testCase.str, func(t *testing.T) { - out := PrefixInList(testCase.str, prefixes) + out := HasAnyPrefix(testCase.str, prefixes) if out != testCase.expected { t.Errorf("incorrect output:") t.Errorf(" str: %#v", testCase.str) diff --git a/android/vts_config.go b/android/vts_config.go index 86f6e7281..9a1df7c99 100644 --- a/android/vts_config.go +++ b/android/vts_config.go @@ -17,6 +17,7 @@ package android import ( "fmt" "io" + "strings" ) func init() { @@ -26,6 +27,8 @@ func init() { type vtsConfigProperties struct { // Override the default (AndroidTest.xml) test manifest file name. Test_config *string + // Additional test suites to add the test to. + Test_suites []string `android:"arch_variant"` } type VtsConfig struct { @@ -50,7 +53,8 @@ func (me *VtsConfig) AndroidMk() AndroidMkData { fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n", *me.properties.Test_config) } - fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := vts") + fmt.Fprintf(w, "LOCAL_COMPATIBILITY_SUITE := vts %s\n", + strings.Join(me.properties.Test_suites, " ")) }, } return androidMkData diff --git a/apex/apex.go b/apex/apex.go index 54a335a5f..002bf5be7 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1024,17 +1024,17 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { // Mark the direct and transitive dependencies of apex bundles so that they // can be built for the apex bundles. func apexDepsMutator(mctx android.TopDownMutatorContext) { - var apexBundleNames []string + var apexBundles []android.ApexInfo var directDep bool if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex { - apexBundleNames = []string{mctx.ModuleName()} + apexBundles = []android.ApexInfo{{mctx.ModuleName(), proptools.Bool(a.properties.Legacy_android10_support)}} directDep = true } else if am, ok := mctx.Module().(android.ApexModule); ok { - apexBundleNames = am.ApexVariations() + apexBundles = am.ApexVariations() directDep = false } - if len(apexBundleNames) == 0 { + if len(apexBundles) == 0 { return } @@ -1042,8 +1042,8 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { depName := mctx.OtherModuleName(child) if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && (directDep || am.DepIsInSameApex(mctx, child)) { - android.UpdateApexDependency(apexBundleNames, depName, directDep) - am.BuildForApexes(apexBundleNames) + android.UpdateApexDependency(apexBundles, depName, directDep) + am.BuildForApexes(apexBundles) } }) } diff --git a/apex/apex_test.go b/apex/apex_test.go index 0420586de..5000c8803 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3437,6 +3437,7 @@ func TestLegacyAndroid10Support(t *testing.T) { apex { name: "myapex", key: "myapex.key", + native_shared_libs: ["mylib"], legacy_android10_support: true, } @@ -3445,12 +3446,54 @@ func TestLegacyAndroid10Support(t *testing.T) { public_key: "testkey.avbpubkey", private_key: "testkey.pem", } - `) + + cc_library { + name: "mylib", + srcs: ["mylib.cpp"], + stl: "libc++", + system_shared_libs: [], + apex_available: [ "myapex" ], + } + + cc_library { + name: "libc++", + srcs: ["mylib.cpp"], + stl: "none", + system_shared_libs: [], + apex_available: [ "myapex" ], + } + + cc_library_static { + name: "libc++demangle", + srcs: ["mylib.cpp"], + stl: "none", + system_shared_libs: [], + } + + cc_library_static { + name: "libunwind_llvm", + srcs: ["mylib.cpp"], + stl: "none", + system_shared_libs: [], + } + `, withUnbundledBuild) module := ctx.ModuleForTests("myapex", "android_common_myapex_image") args := module.Rule("apexRule").Args ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String()) ensureNotContains(t, args["opt_flags"], "--no_hashtree") + + // The copies of the libraries in the apex should have one more dependency than + // the ones outside the apex, namely the unwinder. Ideally we should check + // the dependency names directly here but for some reason the names are blank in + // this test. + for _, lib := range []string{"libc++", "mylib"} { + apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_myapex").Rule("ld").Implicits + nonApexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits + if len(apexImplicits) != len(nonApexImplicits)+1 { + t.Errorf("%q missing unwinder dep", lib) + } + } } func TestJavaSDKLibrary(t *testing.T) { diff --git a/cc/binary.go b/cc/binary.go index 280d17bfb..661264eef 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -200,6 +200,11 @@ func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { module.compiler = NewBaseCompiler() module.linker = binary module.installer = binary + + // Allow module to be added as member of an sdk/module_exports. + module.sdkMemberTypes = []android.SdkMemberType{ + ccBinarySdkMemberType, + } return module, binary } diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go new file mode 100644 index 000000000..53bc065f9 --- /dev/null +++ b/cc/binary_sdk_member.go @@ -0,0 +1,143 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cc + +import ( + "path/filepath" + + "android/soong/android" + "github.com/google/blueprint" +) + +func init() { + android.RegisterSdkMemberType(ccBinarySdkMemberType) +} + +var ccBinarySdkMemberType = &binarySdkMemberType{ + SdkMemberTypeBase: android.SdkMemberTypeBase{ + PropertyName: "native_binaries", + }, +} + +type binarySdkMemberType struct { + android.SdkMemberTypeBase +} + +func (mt *binarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { + targets := mctx.MultiTargets() + for _, lib := range names { + for _, target := range targets { + name, version := StubsLibNameAndVersion(lib) + if version == "" { + version = LatestStubsVersionFor(mctx.Config(), name) + } + mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{ + {Mutator: "version", Variation: version}, + }...), dependencyTag, name) + } + } +} + +func (mt *binarySdkMemberType) IsInstance(module android.Module) bool { + // Check the module to see if it can be used with this module type. + if m, ok := module.(*Module); ok { + for _, allowableMemberType := range m.sdkMemberTypes { + if allowableMemberType == mt { + return true + } + } + } + + return false +} + +func (mt *binarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { + info := mt.organizeVariants(member) + buildSharedNativeBinarySnapshot(info, builder, member) +} + +// Organize the variants by architecture. +func (mt *binarySdkMemberType) organizeVariants(member android.SdkMember) *nativeBinaryInfo { + memberName := member.Name() + info := &nativeBinaryInfo{ + name: memberName, + memberType: mt, + } + + for _, variant := range member.Variants() { + ccModule := variant.(*Module) + + info.archVariantProperties = append(info.archVariantProperties, nativeBinaryInfoProperties{ + name: memberName, + archType: ccModule.Target().Arch.ArchType.String(), + outputFile: ccModule.OutputFile().Path(), + }) + } + + // Initialize the unexported properties that will not be set during the + // extraction process. + info.commonProperties.name = memberName + + // Extract common properties from the arch specific properties. + extractCommonProperties(&info.commonProperties, info.archVariantProperties) + + return info +} + +func buildSharedNativeBinarySnapshot(info *nativeBinaryInfo, builder android.SnapshotBuilder, member android.SdkMember) { + pbm := builder.AddPrebuiltModule(member, "cc_prebuilt_binary") + pbm.AddProperty("compile_multilib", "both") + archProperties := pbm.AddPropertySet("arch") + for _, av := range info.archVariantProperties { + archTypeProperties := archProperties.AddPropertySet(av.archType) + archTypeProperties.AddProperty("srcs", []string{nativeBinaryPathFor(av)}) + + builder.CopyToSnapshot(av.outputFile, nativeBinaryPathFor(av)) + } +} + +const ( + nativeBinaryDir = "bin" +) + +// path to the native binary. Relative to <sdk_root>/<api_dir> +func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string { + return filepath.Join(lib.archType, + nativeBinaryDir, lib.outputFile.Base()) +} + +// nativeBinaryInfoProperties represents properties of a native binary +// +// The exported (capitalized) fields will be examined and may be changed during common value extraction. +// The unexported fields will be left untouched. +type nativeBinaryInfoProperties struct { + // The name of the library, is not exported as this must not be changed during optimization. + name string + + // archType is not exported as if set (to a non default value) it is always arch specific. + // This is "" for common properties. + archType string + + // outputFile is not exported as it is always arch specific. + outputFile android.Path +} + +// nativeBinaryInfo represents a collection of arch-specific modules having the same name +type nativeBinaryInfo struct { + name string + memberType *binarySdkMemberType + archVariantProperties []nativeBinaryInfoProperties + commonProperties nativeBinaryInfoProperties +} diff --git a/cc/builder.go b/cc/builder.go index 3ecfe540c..136263b41 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -55,9 +55,9 @@ var ( }, "ccCmd", "cFlags") - ccNoDeps = pctx.AndroidRemoteStaticRule("ccNoDeps", android.RemoteRuleSupports{Goma: true}, + ccNoDeps = pctx.AndroidStaticRule("ccNoDeps", blueprint.RuleParams{ - Command: "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -o $out $in", + Command: "$relPwd $ccCmd -c $cFlags -o $out $in", CommandDeps: []string{"$ccCmd"}, }, "ccCmd", "cFlags") @@ -95,6 +95,8 @@ type Deps struct { HeaderLibs []string RuntimeLibs []string + StaticUnwinderIfLegacy bool + ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string ObjFiles []string @@ -385,6 +387,7 @@ var ( lateSharedDepTag = DependencyTag{Name: "late shared", Library: true, Shared: true} staticExportDepTag = DependencyTag{Name: "static", Library: true, ReexportFlags: true} lateStaticDepTag = DependencyTag{Name: "late static", Library: true} + staticUnwinderDepTag = DependencyTag{Name: "static unwinder", Library: true} wholeStaticDepTag = DependencyTag{Name: "whole static", Library: true, ReexportFlags: true} headerDepTag = DependencyTag{Name: "header", Library: true} headerExportDepTag = DependencyTag{Name: "header", Library: true, ReexportFlags: true} @@ -1788,6 +1791,12 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { }, depTag, lib) } + if deps.StaticUnwinderIfLegacy && ctx.Config().UnbundledBuild() { + actx.AddVariationDependencies([]blueprint.Variation{ + {Mutator: "link", Variation: "static"}, + }, staticUnwinderDepTag, staticUnwinder(actx)) + } + for _, lib := range deps.LateStaticLibs { actx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "link", Variation: "static"}, @@ -2161,6 +2170,14 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } + if depTag == staticUnwinderDepTag { + if c.ApexProperties.Info.LegacyAndroid10Support { + depTag = StaticDepTag + } else { + return + } + } + // Extract ExplicitlyVersioned field from the depTag and reset it inside the struct. // Otherwise, SharedDepTag and lateSharedDepTag with ExplicitlyVersioned set to true // won't be matched to SharedDepTag and lateSharedDepTag. diff --git a/cc/cflag_artifacts.go b/cc/cflag_artifacts.go index b61f2a8be..855ff25b3 100644 --- a/cc/cflag_artifacts.go +++ b/cc/cflag_artifacts.go @@ -41,12 +41,7 @@ type cflagArtifactsText struct { // filter. func allowedDir(subdir string) bool { subdir += "/" - for _, prefix := range TrackedCFlagsDir { - if strings.HasPrefix(subdir, prefix) { - return true - } - } - return false + return android.HasAnyPrefix(subdir, TrackedCFlagsDir) } func (s *cflagArtifactsText) genFlagFilename(flag string) string { diff --git a/cc/compiler.go b/cc/compiler.go index 1ced451fa..c1a8d96d8 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -241,12 +241,7 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { // Return true if the module is in the WarningAllowedProjects. func warningsAreAllowed(subdir string) bool { subdir += "/" - for _, prefix := range config.WarningAllowedProjects { - if strings.HasPrefix(subdir, prefix) { - return true - } - } - return false + return android.HasAnyPrefix(subdir, config.WarningAllowedProjects) } func addToModuleList(ctx ModuleContext, key android.OnceKey, module string) { @@ -515,7 +510,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps // Exclude directories from manual binder interface whitelisting. //TODO(b/145621474): Move this check into IInterface.h when clang-tidy no longer uses absolute paths. - if android.PrefixInList(ctx.ModuleDir(), allowedManualInterfacePaths) { + if android.HasAnyPrefix(ctx.ModuleDir(), allowedManualInterfacePaths) { flags.Local.CFlags = append(flags.Local.CFlags, "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES") } @@ -604,16 +599,12 @@ var thirdPartyDirPrefixExceptions = []*regexp.Regexp{ func isThirdParty(path string) bool { thirdPartyDirPrefixes := []string{"external/", "vendor/", "hardware/"} - for _, prefix := range thirdPartyDirPrefixes { - if strings.HasPrefix(path, prefix) { - for _, prefix := range thirdPartyDirPrefixExceptions { - if prefix.MatchString(path) { - return false - } + if android.HasAnyPrefix(path, thirdPartyDirPrefixes) { + for _, prefix := range thirdPartyDirPrefixExceptions { + if prefix.MatchString(path) { + return false } - break } } - return true } diff --git a/cc/config/clang.go b/cc/config/clang.go index 26a104bab..0d036999f 100644 --- a/cc/config/clang.go +++ b/cc/config/clang.go @@ -171,10 +171,8 @@ func init() { "-Wno-implicit-int-float-conversion", // New warnings to be fixed after clang-r377782. "-Wno-bitwise-conditional-parentheses", // http://b/148286937 - "-Wno-bool-operation", // http://b/148287141 "-Wno-int-in-bool-context", // http://b/148287349 "-Wno-sizeof-array-div", // http://b/148815709 - "-Wno-tautological-bitwise-compare", // http://b/148831363 "-Wno-tautological-overlap-compare", // http://b/148815696 }, " ")) diff --git a/cc/config/global.go b/cc/config/global.go index 57a585283..d01dd843e 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -127,8 +127,8 @@ var ( // prebuilts/clang default settings. ClangDefaultBase = "prebuilts/clang/host" - ClangDefaultVersion = "clang-r377782" - ClangDefaultShortVersion = "10.0.3" + ClangDefaultVersion = "clang-r377782b" + ClangDefaultShortVersion = "10.0.4" // Directories with warnings from Android.bp files. WarningAllowedProjects = []string{ diff --git a/cc/config/vndk.go b/cc/config/vndk.go index 5cecbd6f5..54f693e0b 100644 --- a/cc/config/vndk.go +++ b/cc/config/vndk.go @@ -19,6 +19,7 @@ package config // has VndkUseCoreVariant set. var VndkMustUseVendorVariantList = []string{ "android.hardware.light-ndk_platform", + "android.hardware.identity-ndk_platform", "android.hardware.nfc@1.2", "android.hardware.power-ndk_platform", "android.hardware.vibrator-ndk_platform", diff --git a/cc/library.go b/cc/library.go index 0bddab534..bca9a9680 100644 --- a/cc/library.go +++ b/cc/library.go @@ -281,11 +281,9 @@ func (f *flagExporter) reexportSystemDirs(dirs ...android.Path) { } func (f *flagExporter) reexportFlags(flags ...string) { - for _, flag := range flags { - if strings.HasPrefix(flag, "-I") || strings.HasPrefix(flag, "-isystem") { - panic(fmt.Errorf("Exporting invalid flag %q: "+ - "use reexportDirs or reexportSystemDirs to export directories", flag)) - } + if android.PrefixInList(flags, "-I") || android.PrefixInList(flags, "-isystem") { + panic(fmt.Errorf("Exporting invalid flag %q: "+ + "use reexportDirs or reexportSystemDirs to export directories", flag)) } f.flags = append(f.flags, flags...) } @@ -151,6 +151,14 @@ func needsLibAndroidSupport(ctx BaseModuleContext) bool { return version < 21 } +func staticUnwinder(ctx android.BaseModuleContext) string { + if ctx.Arch().ArchType == android.Arm { + return "libunwind_llvm" + } else { + return "libgcc_stripped" + } +} + func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps { switch stl.Properties.SelectedStl { case "libstdc++": @@ -172,16 +180,16 @@ func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps { } if ctx.toolchain().Bionic() { if ctx.staticBinary() { - deps.StaticLibs = append(deps.StaticLibs, "libm", "libc") - if ctx.Arch().ArchType == android.Arm { - deps.StaticLibs = append(deps.StaticLibs, "libunwind_llvm") - } else { - deps.StaticLibs = append(deps.StaticLibs, "libgcc_stripped") - } + deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx)) + } else { + deps.StaticUnwinderIfLegacy = true } } case "": // None or error. + if ctx.toolchain().Bionic() && ctx.Module().Name() == "libc++" { + deps.StaticUnwinderIfLegacy = true + } case "ndk_system": // TODO: Make a system STL prebuilt for the NDK. // The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 9b0e7a5d8..6cb987385 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -426,7 +426,7 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g cmd.FlagWithArg("--copy-dex-files=", "false") } - if !anyHavePrefix(preoptFlags, "--compiler-filter=") { + if !android.PrefixInList(preoptFlags, "--compiler-filter=") { var compilerFilter string if contains(global.SystemServerJars, module.Name) { // Jars of system server, use the product option if it is set, speed otherwise. @@ -618,32 +618,4 @@ func contains(l []string, s string) bool { return false } -// remove all elements in a from b, returning a new slice -func filterOut(a []string, b []string) []string { - var ret []string - for _, x := range b { - if !contains(a, x) { - ret = append(ret, x) - } - } - return ret -} - -func replace(l []string, from, to string) { - for i := range l { - if l[i] == from { - l[i] = to - } - } -} - var copyOf = android.CopyOf - -func anyHavePrefix(l []string, prefix string) bool { - for _, x := range l { - if strings.HasPrefix(x, prefix) { - return true - } - } - return false -} diff --git a/java/aar.go b/java/aar.go index 24c5e7d04..6e3b9e6d3 100644 --- a/java/aar.go +++ b/java/aar.go @@ -101,6 +101,7 @@ type aapt struct { usesNonSdkApis bool sdkLibraries []string hasNoCode bool + LoggingParent string splitNames []string splits []split @@ -134,15 +135,8 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths, resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { - hasVersionCode := false - hasVersionName := false - for _, f := range a.aaptProperties.Aaptflags { - if strings.HasPrefix(f, "--version-code") { - hasVersionCode = true - } else if strings.HasPrefix(f, "--version-name") { - hasVersionName = true - } - } + hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code") + hasVersionName := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-name") // Flags specified in Android.bp linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...) @@ -241,7 +235,8 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile) manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries, - a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode) + a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode, + a.LoggingParent) // Add additional manifest files to transitive manifests. additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests) @@ -337,7 +332,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex // Extract assets from the resource package output so that they can be used later in aapt2link // for modules that depend on this one. - if android.PrefixedStringInList(linkFlags, "-A ") || len(assetPackages) > 0 { + if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 { assets := android.PathForModuleOut(ctx, "assets.zip") ctx.Build(pctx, android.BuildParams{ Rule: extractAssetsRule, diff --git a/java/android_manifest.go b/java/android_manifest.go index e3646f5f9..9a71be28a 100644 --- a/java/android_manifest.go +++ b/java/android_manifest.go @@ -53,7 +53,7 @@ var optionalUsesLibs = []string{ // Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string, - isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool) android.Path { + isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path { var args []string if isLibrary { @@ -91,6 +91,9 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext args = append(args, "--has-no-code") } + if loggingParent != "" { + args = append(args, "--logging-parent", loggingParent) + } var deps android.Paths targetSdkVersion, err := sdkContext.targetSdkVersion().effectiveVersionString(ctx) if err != nil { diff --git a/java/app.go b/java/app.go index 02f3e7fc0..71bad683c 100755 --- a/java/app.go +++ b/java/app.go @@ -111,6 +111,9 @@ type overridableAppProperties struct { // the package name of this app. The package name in the manifest file is used if one was not given. Package_name *string + + // the logging parent of this app. + Logging_parent *string } type AndroidApp struct { @@ -273,13 +276,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { aaptLinkFlags := []string{} // Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided. - hasProduct := false - for _, f := range a.aaptProperties.Aaptflags { - if strings.HasPrefix(f, "--product") { - hasProduct = true - break - } - } + hasProduct := android.PrefixInList(a.aaptProperties.Aaptflags, "--product") if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 { aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics()) } @@ -309,7 +306,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { a.aapt.splitNames = a.appProperties.Package_splits a.aapt.sdkLibraries = a.exportedSdkLibs - + a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent) a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...) // apps manifests are handled by aapt, don't let Module see them diff --git a/java/app_test.go b/java/app_test.go index c86b038af..6d94160fa 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1181,6 +1181,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "bar", base: "foo", certificate: ":new_certificate", + logging_parent: "bah", } android_app_certificate { @@ -1196,37 +1197,41 @@ func TestOverrideAndroidApp(t *testing.T) { `) expectedVariants := []struct { - moduleName string - variantName string - apkName string - apkPath string - signFlag string - overrides []string - aaptFlag string + moduleName string + variantName string + apkName string + apkPath string + signFlag string + overrides []string + aaptFlag string + logging_parent string }{ { - moduleName: "foo", - variantName: "android_common", - apkPath: "/target/product/test_device/system/app/foo/foo.apk", - signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", - overrides: []string{"qux"}, - aaptFlag: "", + moduleName: "foo", + variantName: "android_common", + apkPath: "/target/product/test_device/system/app/foo/foo.apk", + signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + overrides: []string{"qux"}, + aaptFlag: "", + logging_parent: "", }, { - moduleName: "bar", - variantName: "android_common_bar", - apkPath: "/target/product/test_device/system/app/bar/bar.apk", - signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", - overrides: []string{"qux", "foo"}, - aaptFlag: "", + moduleName: "bar", + variantName: "android_common_bar", + apkPath: "/target/product/test_device/system/app/bar/bar.apk", + signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", + overrides: []string{"qux", "foo"}, + aaptFlag: "", + logging_parent: "bah", }, { - moduleName: "baz", - variantName: "android_common_baz", - apkPath: "/target/product/test_device/system/app/baz/baz.apk", - signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", - overrides: []string{"qux", "foo"}, - aaptFlag: "--rename-manifest-package org.dandroid.bp", + moduleName: "baz", + variantName: "android_common_baz", + apkPath: "/target/product/test_device/system/app/baz/baz.apk", + signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + overrides: []string{"qux", "foo"}, + aaptFlag: "--rename-manifest-package org.dandroid.bp", + logging_parent: "", }, } for _, expected := range expectedVariants { @@ -1260,6 +1265,13 @@ func TestOverrideAndroidApp(t *testing.T) { expected.overrides, mod.appProperties.Overrides) } + // Test Overridable property: Logging_parent + logging_parent := mod.aapt.LoggingParent + if expected.logging_parent != logging_parent { + t.Errorf("Incorrect overrides property value for logging parent, expected: %q, got: %q", + expected.logging_parent, logging_parent) + } + // Check the package renaming flag, if exists. res := variant.Output("package-res.apk") aapt2Flags := res.Args["flags"] diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 96f8042a0..28f56d24a 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -15,6 +15,7 @@ package java import ( + "fmt" "path/filepath" "strings" @@ -29,14 +30,29 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string { return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string { global := dexpreopt.GetGlobalConfig(ctx) var systemServerClasspathLocations []string - for _, m := range *DexpreoptedSystemServerJars(ctx.Config()) { + var dexpreoptJars = *DexpreoptedSystemServerJars(ctx.Config()) + // 1) The jars that are dexpreopted. + for _, m := range dexpreoptJars { systemServerClasspathLocations = append(systemServerClasspathLocations, filepath.Join("/system/framework", m+".jar")) } + // 2) The jars that are from an updatable apex. for _, m := range global.UpdatableSystemServerJars { systemServerClasspathLocations = append(systemServerClasspathLocations, dexpreopt.GetJarLocationFromApexJarPair(m)) } + // 3) The jars from make (which are not updatable, not preopted). + for _, m := range dexpreopt.NonUpdatableSystemServerJars(ctx, global) { + if !android.InList(m, dexpreoptJars) { + systemServerClasspathLocations = append(systemServerClasspathLocations, + filepath.Join("/system/framework", m+".jar")) + } + } + if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) { + panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d", + len(systemServerClasspathLocations), + len(global.SystemServerJars)+len(global.UpdatableSystemServerJars))) + } return systemServerClasspathLocations }) } diff --git a/java/droiddoc.go b/java/droiddoc.go index 959f1c734..fd4b90df3 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -547,10 +547,10 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { case bootClasspathTag: if dep, ok := module.(Dependency); ok { deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...) - } else if sm, ok := module.(*SystemModules); ok { + } else if sm, ok := module.(SystemModulesProvider); ok { // A system modules dependency has been added to the bootclasspath // so add its libs to the bootclasspath. - deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...) + deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...) } else { panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName())) } @@ -578,11 +578,9 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { if deps.systemModules != nil { panic("Found two system module dependencies") } - sm := module.(*SystemModules) - if sm.outputDir == nil && len(sm.outputDeps) == 0 { - panic("Missing directory for system module dependency") - } - deps.systemModules = &systemModules{sm.outputDir, sm.outputDeps} + sm := module.(SystemModulesProvider) + outputDir, outputDeps := sm.OutputDirAndDeps() + deps.systemModules = &systemModules{outputDir, outputDeps} } }) // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs @@ -605,11 +603,8 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { continue } packageName := strings.ReplaceAll(filepath.Dir(src.Rel()), "/", ".") - for _, pkg := range filterPackages { - if strings.HasPrefix(packageName, pkg) { - filtered = append(filtered, src) - break - } + if android.HasAnyPrefix(packageName, filterPackages) { + filtered = append(filtered, src) } } return filtered diff --git a/java/java.go b/java/java.go index c3e2c9656..462dba809 100644 --- a/java/java.go +++ b/java/java.go @@ -1031,18 +1031,16 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case bootClasspathTag: // If a system modules dependency has been added to the bootclasspath // then add its libs to the bootclasspath. - sm := module.(*SystemModules) - deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...) + sm := module.(SystemModulesProvider) + deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...) case systemModulesTag: if deps.systemModules != nil { panic("Found two system module dependencies") } - sm := module.(*SystemModules) - if sm.outputDir == nil || len(sm.outputDeps) == 0 { - panic("Missing directory for system module dependency") - } - deps.systemModules = &systemModules{sm.outputDir, sm.outputDeps} + sm := module.(SystemModulesProvider) + outputDir, outputDeps := sm.OutputDirAndDeps() + deps.systemModules = &systemModules{outputDir, outputDeps} } } }) diff --git a/java/java_test.go b/java/java_test.go index a2226b59e..52b3bc087 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -982,6 +982,65 @@ func TestDroiddoc(t *testing.T) { } } +func TestDroidstubsWithSystemModules(t *testing.T) { + ctx, _ := testJava(t, ` + droidstubs { + name: "stubs-source-system-modules", + srcs: [ + "bar-doc/*.java", + ], + sdk_version: "none", + system_modules: "source-system-modules", + } + + java_library { + name: "source-jar", + srcs: [ + "a.java", + ], + } + + java_system_modules { + name: "source-system-modules", + libs: ["source-jar"], + } + + droidstubs { + name: "stubs-prebuilt-system-modules", + srcs: [ + "bar-doc/*.java", + ], + sdk_version: "none", + system_modules: "prebuilt-system-modules", + } + + java_import { + name: "prebuilt-jar", + jars: ["a.jar"], + } + + java_system_modules_import { + name: "prebuilt-system-modules", + libs: ["prebuilt-jar"], + } + `) + + checkSystemModulesUseByDroidstubs(t, ctx, "stubs-source-system-modules", "source-jar.jar") + + checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar") +} + +func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) { + metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava") + var systemJars []string + for _, i := range metalavaRule.Implicits { + systemJars = append(systemJars, i.Base()) + } + if len(systemJars) != 1 || systemJars[0] != systemJar { + t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars) + } +} + func TestJarGenrules(t *testing.T) { ctx, _ := testJava(t, ` java_library { @@ -1377,3 +1436,59 @@ func TestJavaSystemModulesImport(t *testing.T) { } } } + +func TestJavaLibraryWithSystemModules(t *testing.T) { + ctx, _ := testJava(t, ` + java_library { + name: "lib-with-source-system-modules", + srcs: [ + "a.java", + ], + sdk_version: "none", + system_modules: "source-system-modules", + } + + java_library { + name: "source-jar", + srcs: [ + "a.java", + ], + } + + java_system_modules { + name: "source-system-modules", + libs: ["source-jar"], + } + + java_library { + name: "lib-with-prebuilt-system-modules", + srcs: [ + "a.java", + ], + sdk_version: "none", + system_modules: "prebuilt-system-modules", + } + + java_import { + name: "prebuilt-jar", + jars: ["a.jar"], + } + + java_system_modules_import { + name: "prebuilt-system-modules", + libs: ["prebuilt-jar"], + } + `) + + checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar") + + checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar") +} + +func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) { + javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac") + bootClasspath := javacRule.Args["bootClasspath"] + if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) { + t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath) + } +} diff --git a/java/system_modules.go b/java/system_modules.go index 731503fd0..47de6e327 100644 --- a/java/system_modules.go +++ b/java/system_modules.go @@ -117,6 +117,15 @@ func SystemModulesFactory() android.Module { return module } +type SystemModulesProvider interface { + HeaderJars() android.Paths + OutputDirAndDeps() (android.Path, android.Paths) +} + +var _ SystemModulesProvider = (*SystemModules)(nil) + +var _ SystemModulesProvider = (*systemModulesImport)(nil) + type SystemModules struct { android.ModuleBase android.DefaultableModuleBase @@ -136,6 +145,17 @@ type SystemModulesProperties struct { Libs []string } +func (system *SystemModules) HeaderJars() android.Paths { + return system.headerJars +} + +func (system *SystemModules) OutputDirAndDeps() (android.Path, android.Paths) { + if system.outputDir == nil || len(system.outputDeps) == 0 { + panic("Missing directory for system module dependency") + } + return system.outputDir, system.outputDeps +} + func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) { var jars android.Paths diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py index 945bc1832..c59732bb9 100755 --- a/scripts/manifest_fixer.py +++ b/scripts/manifest_fixer.py @@ -51,6 +51,9 @@ def parse_args(): help='specify additional <uses-library> tag to add. android:requred is set to false') parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true', help='manifest is for a package built against the platform') + parser.add_argument('--logging-parent', dest='logging_parent', default='', + help=('specify logging parent as an additional <meta-data> tag. ' + 'This value is ignored if the logging_parent meta-data tag is present.')) parser.add_argument('--use-embedded-dex', dest='use_embedded_dex', action='store_true', help=('specify if the app wants to use embedded dex and avoid extracted,' 'locally compiled code. Must not conflict if already declared ' @@ -124,6 +127,52 @@ def raise_min_sdk_version(doc, min_sdk_version, target_sdk_version, library): element.setAttributeNode(target_attr) +def add_logging_parent(doc, logging_parent_value): + """Add logging parent as an additional <meta-data> tag. + + Args: + doc: The XML document. May be modified by this function. + logging_parent_value: A string representing the logging + parent value. + Raises: + RuntimeError: Invalid manifest + """ + manifest = parse_manifest(doc) + + logging_parent_key = 'android.content.pm.LOGGING_PARENT' + elems = get_children_with_tag(manifest, 'application') + application = elems[0] if len(elems) == 1 else None + if len(elems) > 1: + raise RuntimeError('found multiple <application> tags') + elif not elems: + application = doc.createElement('application') + indent = get_indent(manifest.firstChild, 1) + first = manifest.firstChild + manifest.insertBefore(doc.createTextNode(indent), first) + manifest.insertBefore(application, first) + + indent = get_indent(application.firstChild, 2) + + last = application.lastChild + if last is not None and last.nodeType != minidom.Node.TEXT_NODE: + last = None + + if not find_child_with_attribute(application, 'meta-data', android_ns, + 'name', logging_parent_key): + ul = doc.createElement('meta-data') + ul.setAttributeNS(android_ns, 'android:name', logging_parent_key) + ul.setAttributeNS(android_ns, 'android:value', logging_parent_value) + application.insertBefore(doc.createTextNode(indent), last) + application.insertBefore(ul, last) + last = application.lastChild + + # align the closing tag with the opening tag if it's not + # indented + if last and last.nodeType != minidom.Node.TEXT_NODE: + indent = get_indent(application.previousSibling, 1) + application.appendChild(doc.createTextNode(indent)) + + def add_uses_libraries(doc, new_uses_libraries, required): """Add additional <uses-library> tags @@ -291,6 +340,9 @@ def main(): if args.uses_non_sdk_api: add_uses_non_sdk_api(doc) + if args.logging_parent: + add_logging_parent(doc, args.logging_parent) + if args.use_embedded_dex: add_use_embedded_dex(doc) diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py index ea8095e48..d6e7f2674 100755 --- a/scripts/manifest_fixer_test.py +++ b/scripts/manifest_fixer_test.py @@ -226,6 +226,47 @@ class RaiseMinSdkVersionTest(unittest.TestCase): self.assertEqual(output, expected) +class AddLoggingParentTest(unittest.TestCase): + """Unit tests for add_logging_parent function.""" + + def add_logging_parent_test(self, input_manifest, logging_parent=None): + doc = minidom.parseString(input_manifest) + if logging_parent: + manifest_fixer.add_logging_parent(doc, logging_parent) + output = StringIO.StringIO() + manifest_fixer.write_xml(output, doc) + return output.getvalue() + + manifest_tmpl = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' + '%s' + '</manifest>\n') + + def uses_logging_parent(self, logging_parent=None): + attrs = '' + if logging_parent: + meta_text = ('<meta-data android:name="android.content.pm.LOGGING_PARENT" ' + 'android:value="%s"/>\n') % (logging_parent) + attrs += ' <application>\n %s </application>\n' % (meta_text) + + return attrs + + def test_no_logging_parent(self): + """Tests manifest_fixer with no logging_parent.""" + manifest_input = self.manifest_tmpl % '' + expected = self.manifest_tmpl % self.uses_logging_parent() + output = self.add_logging_parent_test(manifest_input) + self.assertEqual(output, expected) + + def test_logging_parent(self): + """Tests manifest_fixer with no logging_parent.""" + manifest_input = self.manifest_tmpl % '' + expected = self.manifest_tmpl % self.uses_logging_parent('FOO') + output = self.add_logging_parent_test(manifest_input, 'FOO') + self.assertEqual(output, expected) + + class AddUsesLibrariesTest(unittest.TestCase): """Unit tests for add_uses_libraries function.""" diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go index 9a75610f6..8c32d8cad 100644 --- a/sdk/cc_sdk_test.go +++ b/sdk/cc_sdk_test.go @@ -337,6 +337,68 @@ arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h ) } +func TestSnapshotWithCcBinary(t *testing.T) { + result := testSdkWithCc(t, ` + module_exports { + name: "mymodule_exports", + native_binaries: ["mynativebinary"], + } + + cc_binary { + name: "mynativebinary", + srcs: [ + "Test.cpp", + ], + compile_multilib: "both", + system_shared_libs: [], + stl: "none", + } + `) + + result.CheckSnapshot("mymodule_exports", "android_common", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +cc_prebuilt_binary { + name: "mymodule_exports_mynativebinary@current", + sdk_member_name: "mynativebinary", + compile_multilib: "both", + arch: { + arm64: { + srcs: ["arm64/bin/mynativebinary"], + }, + arm: { + srcs: ["arm/bin/mynativebinary"], + }, + }, +} + +cc_prebuilt_binary { + name: "mynativebinary", + prefer: false, + compile_multilib: "both", + arch: { + arm64: { + srcs: ["arm64/bin/mynativebinary"], + }, + arm: { + srcs: ["arm/bin/mynativebinary"], + }, + }, +} + +module_exports_snapshot { + name: "mymodule_exports@current", + native_binaries: ["mymodule_exports_mynativebinary@current"], +} +`), + checkAllCopyRules(` +.intermediates/mynativebinary/android_arm64_armv8-a/mynativebinary -> arm64/bin/mynativebinary +.intermediates/mynativebinary/android_arm_armv7-a-neon/mynativebinary -> arm/bin/mynativebinary +`), + ) +} + func TestSnapshotWithCcSharedLibrary(t *testing.T) { result := testSdkWithCc(t, ` sdk { |