diff --git a/android/module.go b/android/module.go index 2062a4d4d..22c9b4468 100644 --- a/android/module.go +++ b/android/module.go @@ -1833,7 +1833,7 @@ func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag { // A regexp for removing boilerplate from BaseDependencyTag from the string representation of // a dependency tag. -var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:blueprint.BaseDependencyTag{}\E(, )?`) +var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`) // PrettyPrintTag returns string representation of the tag, but prefers // custom String() method if available. @@ -1844,7 +1844,7 @@ func PrettyPrintTag(tag blueprint.DependencyTag) string { } // Otherwise, get a default string representation of the tag's struct. - tagString := fmt.Sprintf("%#v", tag) + tagString := fmt.Sprintf("%T: %+v", tag, tag) // Remove the boilerplate from BaseDependencyTag as it adds no value. tagString = tagCleaner.ReplaceAllString(tagString, "") diff --git a/apex/apex_test.go b/apex/apex_test.go index 7db61d5cf..f09c2bc08 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -4433,11 +4433,11 @@ func TestApexAvailable_DirectDep(t *testing.T) { func TestApexAvailable_IndirectDep(t *testing.T) { // libbbaz is an indirect dep testApexError(t, `requires "libbaz" that is not available for the APEX. Dependency path: -.*via tag apex\.dependencyTag.*"sharedLib".* +.*via tag apex\.dependencyTag.*name:sharedLib.* .*-> libfoo.*link:shared.* -.*via tag cc\.DependencyTag.*"shared".* +.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.* .*-> libbar.*link:shared.* -.*via tag cc\.DependencyTag.*"shared".* +.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.* .*-> libbaz.*link:shared.*`, ` apex { name: "myapex", diff --git a/cc/cc.go b/cc/cc.go index 962da4c28..d099b043e 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -425,44 +425,130 @@ type xref interface { XrefCcFiles() android.Paths } +type libraryDependencyKind int + +const ( + headerLibraryDependency = iota + sharedLibraryDependency + staticLibraryDependency +) + +func (k libraryDependencyKind) String() string { + switch k { + case headerLibraryDependency: + return "headerLibraryDependency" + case sharedLibraryDependency: + return "sharedLibraryDependency" + case staticLibraryDependency: + return "staticLibraryDependency" + default: + panic(fmt.Errorf("unknown libraryDependencyKind %d", k)) + } +} + +type libraryDependencyOrder int + +const ( + earlyLibraryDependency = -1 + normalLibraryDependency = 0 + lateLibraryDependency = 1 +) + +func (o libraryDependencyOrder) String() string { + switch o { + case earlyLibraryDependency: + return "earlyLibraryDependency" + case normalLibraryDependency: + return "normalLibraryDependency" + case lateLibraryDependency: + return "lateLibraryDependency" + default: + panic(fmt.Errorf("unknown libraryDependencyOrder %d", o)) + } +} + +// libraryDependencyTag is used to tag dependencies on libraries. Unlike many dependency +// tags that have a set of predefined tag objects that are reused for each dependency, a +// libraryDependencyTag is designed to contain extra metadata and is constructed as needed. +// That means that comparing a libraryDependencyTag for equality will only be equal if all +// of the metadata is equal. Most usages will want to type assert to libraryDependencyTag and +// then check individual metadata fields instead. +type libraryDependencyTag struct { + blueprint.BaseDependencyTag + + // These are exported so that fmt.Printf("%#v") can call their String methods. + Kind libraryDependencyKind + Order libraryDependencyOrder + + wholeStatic bool + + reexportFlags bool + explicitlyVersioned bool + dataLib bool + ndk bool + + staticUnwinder bool + + makeSuffix string +} + +// header returns true if the libraryDependencyTag is tagging a header lib dependency. +func (d libraryDependencyTag) header() bool { + return d.Kind == headerLibraryDependency +} + +// shared returns true if the libraryDependencyTag is tagging a shared lib dependency. +func (d libraryDependencyTag) shared() bool { + return d.Kind == sharedLibraryDependency +} + +// shared returns true if the libraryDependencyTag is tagging a static lib dependency. +func (d libraryDependencyTag) static() bool { + return d.Kind == staticLibraryDependency +} + +// dependencyTag is used for tagging miscellanous dependency types that don't fit into +// libraryDependencyTag. Each tag object is created globally and reused for multiple +// dependencies (although since the object contains no references, assigning a tag to a +// variable and modifying it will not modify the original). Users can compare the tag +// returned by ctx.OtherModuleDependencyTag against the global original +type dependencyTag struct { + blueprint.BaseDependencyTag + name string +} + var ( - dataLibDepTag = DependencyTag{Name: "data_lib", Library: true, Shared: true} - sharedExportDepTag = DependencyTag{Name: "shared", Library: true, Shared: true, ReexportFlags: true} - earlySharedDepTag = DependencyTag{Name: "early_shared", Library: true, Shared: true} - 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} - genSourceDepTag = DependencyTag{Name: "gen source"} - genHeaderDepTag = DependencyTag{Name: "gen header"} - genHeaderExportDepTag = DependencyTag{Name: "gen header", ReexportFlags: true} - objDepTag = DependencyTag{Name: "obj"} - linkerFlagsDepTag = DependencyTag{Name: "linker flags file"} - dynamicLinkerDepTag = DependencyTag{Name: "dynamic linker"} - reuseObjTag = DependencyTag{Name: "reuse objects"} - staticVariantTag = DependencyTag{Name: "static variant"} - ndkStubDepTag = DependencyTag{Name: "ndk stub", Library: true} - ndkLateStubDepTag = DependencyTag{Name: "ndk late stub", Library: true} - vndkExtDepTag = DependencyTag{Name: "vndk extends", Library: true} - runtimeDepTag = DependencyTag{Name: "runtime lib"} - testPerSrcDepTag = DependencyTag{Name: "test_per_src"} + genSourceDepTag = dependencyTag{name: "gen source"} + genHeaderDepTag = dependencyTag{name: "gen header"} + genHeaderExportDepTag = dependencyTag{name: "gen header export"} + objDepTag = dependencyTag{name: "obj"} + linkerFlagsDepTag = dependencyTag{name: "linker flags file"} + dynamicLinkerDepTag = dependencyTag{name: "dynamic linker"} + reuseObjTag = dependencyTag{name: "reuse objects"} + staticVariantTag = dependencyTag{name: "static variant"} + vndkExtDepTag = dependencyTag{name: "vndk extends"} + dataLibDepTag = dependencyTag{name: "data lib"} + runtimeDepTag = dependencyTag{name: "runtime lib"} + testPerSrcDepTag = dependencyTag{name: "test_per_src"} ) func IsSharedDepTag(depTag blueprint.DependencyTag) bool { - ccDepTag, ok := depTag.(DependencyTag) - return ok && ccDepTag.Shared + ccLibDepTag, ok := depTag.(libraryDependencyTag) + return ok && ccLibDepTag.shared() +} + +func IsStaticDepTag(depTag blueprint.DependencyTag) bool { + ccLibDepTag, ok := depTag.(libraryDependencyTag) + return ok && ccLibDepTag.static() } func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool { - ccDepTag, ok := depTag.(DependencyTag) + ccDepTag, ok := depTag.(dependencyTag) return ok && ccDepTag == runtimeDepTag } func IsTestPerSrcDepTag(depTag blueprint.DependencyTag) bool { - ccDepTag, ok := depTag.(DependencyTag) + ccDepTag, ok := depTag.(dependencyTag) return ok && ccDepTag == testPerSrcDepTag } @@ -1859,9 +1945,9 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { vendorSnapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config()) for _, lib := range deps.HeaderLibs { - depTag := headerDepTag + depTag := libraryDependencyTag{Kind: headerLibraryDependency} if inList(lib, deps.ReexportHeaderLibHeaders) { - depTag = headerExportDepTag + depTag.reexportFlags = true } lib = rewriteSnapshotLibs(lib, vendorSnapshotHeaderLibs) @@ -1884,7 +1970,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { vendorSnapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config()) for _, lib := range deps.WholeStaticLibs { - depTag := wholeStaticDepTag + depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true} if impl, ok := syspropImplLibraries[lib]; ok { lib = impl } @@ -1897,9 +1983,9 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { } for _, lib := range deps.StaticLibs { - depTag := StaticDepTag + depTag := libraryDependencyTag{Kind: staticLibraryDependency} if inList(lib, deps.ReexportStaticLibHeaders) { - depTag = staticExportDepTag + depTag.reexportFlags = true } if impl, ok := syspropImplLibraries[lib]; ok { @@ -1917,24 +2003,26 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { // so that native libraries/binaries are linked with static unwinder // because Q libc doesn't have unwinder APIs if deps.StaticUnwinderIfLegacy { + depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true} actx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "link", Variation: "static"}, - }, staticUnwinderDepTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs)) + }, depTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs)) } for _, lib := range deps.LateStaticLibs { + depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency} actx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "link", Variation: "static"}, - }, lateStaticDepTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)) + }, depTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)) } - addSharedLibDependencies := func(depTag DependencyTag, name string, version string) { + addSharedLibDependencies := func(depTag libraryDependencyTag, name string, version string) { var variations []blueprint.Variation variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"}) if version != "" && VersionVariantAvailable(c) { // Version is explicitly specified. i.e. libFoo#30 variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version}) - depTag.ExplicitlyVersioned = true + depTag.explicitlyVersioned = true } actx.AddVariationDependencies(variations, depTag, name) @@ -1956,12 +2044,9 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { var sharedLibNames []string for _, lib := range deps.SharedLibs { - depTag := SharedDepTag - if c.static() { - depTag = SharedFromStaticDepTag - } + depTag := libraryDependencyTag{Kind: sharedLibraryDependency} if inList(lib, deps.ReexportSharedLibHeaders) { - depTag = sharedExportDepTag + depTag.reexportFlags = true } if impl, ok := syspropImplLibraries[lib]; ok { @@ -1981,7 +2066,8 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { // linking against both the stubs lib and the non-stubs lib at the same time. continue } - addSharedLibDependencies(lateSharedDepTag, lib, "") + depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency} + addSharedLibDependencies(depTag, lib, "") } actx.AddVariationDependencies([]blueprint.Variation{ @@ -2020,10 +2106,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { } version := ctx.sdkVersion() + + ndkStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, ndk: true, makeSuffix: "." + version} actx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "ndk_api", Variation: version}, {Mutator: "link", Variation: "shared"}, }, ndkStubDepTag, variantNdkLibs...) + + ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version} actx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "ndk_api", Variation: version}, {Mutator: "link", Variation: "shared"}, @@ -2047,7 +2137,19 @@ func BeginMutator(ctx android.BottomUpMutatorContext) { // Whether a module can link to another module, taking into // account NDK linking. -func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to LinkableInterface, tag DependencyTag) { +func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to LinkableInterface, + tag blueprint.DependencyTag) { + + switch t := tag.(type) { + case dependencyTag: + if t != vndkExtDepTag { + return + } + case libraryDependencyTag: + default: + return + } + if from.Module().Target().Os != android.Android { // Host code is not restricted return @@ -2205,8 +2307,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directStaticDeps := []LinkableInterface{} directSharedDeps := []LinkableInterface{} - vendorPublicLibraries := vendorPublicLibraries(ctx.Config()) - reexportExporter := func(exporter exportedFlagsProducer) { depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.exportedDirs()...) depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...) @@ -2316,39 +2416,24 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } - if depTag == staticUnwinderDepTag { - // Use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859) - if c.apexSdkVersion <= android.SdkVersion_Android10 { - depTag = StaticDepTag - } else { + checkLinkType(ctx, c, ccDep, depTag) + + linkFile := ccDep.OutputFile() + + if libDepTag, ok := depTag.(libraryDependencyTag); ok { + // Only use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859) + if libDepTag.staticUnwinder && c.apexSdkVersion > android.SdkVersion_Android10 { 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. - explicitlyVersioned := false - if t, ok := depTag.(DependencyTag); ok { - explicitlyVersioned = t.ExplicitlyVersioned - t.ExplicitlyVersioned = false - depTag = t - } - - if t, ok := depTag.(DependencyTag); ok && t.Library { - depIsStatic := false - switch depTag { - case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag: - depIsStatic = true - } - if ccDep.CcLibrary() && !depIsStatic { + if ccDep.CcLibrary() && !libDepTag.static() { depIsStubs := ccDep.BuildStubs() depHasStubs := VersionVariantAvailable(c) && ccDep.HasStubsVariants() depInSameApex := android.DirectlyInApex(c.ApexName(), depName) depInPlatform := !android.DirectlyInAnyApex(ctx, depName) var useThisDep bool - if depIsStubs && explicitlyVersioned { + if depIsStubs && libDepTag.explicitlyVersioned { // Always respect dependency to the versioned stubs (i.e. libX#10) useThisDep = true } else if !depHasStubs { @@ -2380,7 +2465,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } // when to use (unspecified) stubs, check min_sdk_version and choose the right one - if useThisDep && depIsStubs && !explicitlyVersioned { + if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned { versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion) if err != nil { ctx.OtherModuleErrorf(dep, err.Error()) @@ -2425,7 +2510,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, i.exportedDeps()...) depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...) - if t.ReexportFlags { + if libDepTag.reexportFlags { reexportExporter(i) // Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library. // Re-exported shared library headers must be included as well since they can help us with type information @@ -2437,210 +2522,178 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } } - checkLinkType(ctx, c, ccDep, t) - } - var ptr *android.Paths - var depPtr *android.Paths + var ptr *android.Paths + var depPtr *android.Paths - linkFile := ccDep.OutputFile() - depFile := android.OptionalPath{} + depFile := android.OptionalPath{} - switch depTag { - case ndkStubDepTag, SharedDepTag, SharedFromStaticDepTag, sharedExportDepTag: - ptr = &depPaths.SharedLibs - depPtr = &depPaths.SharedLibsDeps - depFile = ccDep.Toc() - directSharedDeps = append(directSharedDeps, ccDep) - - case earlySharedDepTag: - ptr = &depPaths.EarlySharedLibs - depPtr = &depPaths.EarlySharedLibsDeps - depFile = ccDep.Toc() - directSharedDeps = append(directSharedDeps, ccDep) - case lateSharedDepTag, ndkLateStubDepTag: - ptr = &depPaths.LateSharedLibs - depPtr = &depPaths.LateSharedLibsDeps - depFile = ccDep.Toc() - case StaticDepTag, staticExportDepTag: - ptr = nil - directStaticDeps = append(directStaticDeps, ccDep) - case lateStaticDepTag: - ptr = &depPaths.LateStaticLibs - case wholeStaticDepTag: - ptr = &depPaths.WholeStaticLibs - if !ccDep.CcLibraryInterface() || !ccDep.Static() { - ctx.ModuleErrorf("module %q not a static library", depName) - return - } - - // Because the static library objects are included, this only makes sense - // in the context of proper cc.Modules. - if ccWholeStaticLib, ok := ccDep.(*Module); ok { - staticLib := ccWholeStaticLib.linker.(libraryInterface) - if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil { - postfix := " (required by " + ctx.OtherModuleName(dep) + ")" - for i := range missingDeps { - missingDeps[i] += postfix - } - ctx.AddMissingDependencies(missingDeps) + switch { + case libDepTag.header(): + // nothing + case libDepTag.shared(): + ptr = &depPaths.SharedLibs + switch libDepTag.Order { + case earlyLibraryDependency: + ptr = &depPaths.EarlySharedLibs + depPtr = &depPaths.EarlySharedLibsDeps + case normalLibraryDependency: + ptr = &depPaths.SharedLibs + depPtr = &depPaths.SharedLibsDeps + directSharedDeps = append(directSharedDeps, ccDep) + case lateLibraryDependency: + ptr = &depPaths.LateSharedLibs + depPtr = &depPaths.LateSharedLibsDeps + default: + panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order)) } - if _, ok := ccWholeStaticLib.linker.(prebuiltLinkerInterface); ok { - depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path()) - } else { - depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs()) - } - } else { - ctx.ModuleErrorf( - "non-cc.Modules cannot be included as whole static libraries.", depName) - return - } - case headerDepTag: - // Nothing - case objDepTag: - depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path()) - case CrtBeginDepTag: - depPaths.CrtBegin = linkFile - case CrtEndDepTag: - depPaths.CrtEnd = linkFile - case dynamicLinkerDepTag: - depPaths.DynamicLinker = linkFile - } - - switch depTag { - case StaticDepTag, staticExportDepTag, lateStaticDepTag: - if !ccDep.CcLibraryInterface() || !ccDep.Static() { - ctx.ModuleErrorf("module %q not a static library", depName) - return - } - - // When combining coverage files for shared libraries and executables, coverage files - // in static libraries act as if they were whole static libraries. The same goes for - // source based Abi dump files. - if c, ok := ccDep.(*Module); ok { - staticLib := c.linker.(libraryInterface) - depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles, - staticLib.objs().coverageFiles...) - depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles, - staticLib.objs().sAbiDumpFiles...) - } else if c, ok := ccDep.(LinkableInterface); ok { - // Handle non-CC modules here - depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles, - c.CoverageFiles()...) - } - } - - if ptr != nil { - if !linkFile.Valid() { - if !ctx.Config().AllowMissingDependencies() { - ctx.ModuleErrorf("module %q missing output file", depName) - } else { - ctx.AddMissingDependencies([]string{depName}) - } - return - } - *ptr = append(*ptr, linkFile.Path()) - } - - if depPtr != nil { - dep := depFile - if !dep.Valid() { - dep = linkFile - } - *depPtr = append(*depPtr, dep.Path()) - } - - vendorSuffixModules := vendorSuffixModules(ctx.Config()) - - baseLibName := func(depName string) string { - libName := strings.TrimSuffix(depName, llndkLibrarySuffix) - libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix) - libName = strings.TrimPrefix(libName, "prebuilt_") - return libName - } - - makeLibName := func(depName string) string { - libName := baseLibName(depName) - isLLndk := isLlndkLibrary(libName, ctx.Config()) - isVendorPublicLib := inList(libName, *vendorPublicLibraries) - bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk - - if c, ok := ccDep.(*Module); ok { - // Use base module name for snapshots when exporting to Makefile. - if c.isSnapshotPrebuilt() { - baseName := c.BaseModuleName() - - if c.IsVndk() { - return baseName + ".vendor" + depFile = ccDep.Toc() + case libDepTag.static(): + if libDepTag.wholeStatic { + ptr = &depPaths.WholeStaticLibs + if !ccDep.CcLibraryInterface() || !ccDep.Static() { + ctx.ModuleErrorf("module %q not a static library", depName) + return } - if vendorSuffixModules[baseName] { - return baseName + ".vendor" + // Because the static library objects are included, this only makes sense + // in the context of proper cc.Modules. + if ccWholeStaticLib, ok := ccDep.(*Module); ok { + staticLib := ccWholeStaticLib.linker.(libraryInterface) + if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil { + postfix := " (required by " + ctx.OtherModuleName(dep) + ")" + for i := range missingDeps { + missingDeps[i] += postfix + } + ctx.AddMissingDependencies(missingDeps) + } + if _, ok := ccWholeStaticLib.linker.(prebuiltLinkerInterface); ok { + depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path()) + } else { + depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs()) + } } else { - return baseName + ctx.ModuleErrorf( + "non-cc.Modules cannot be included as whole static libraries.", depName) + return + } + + } else { + switch libDepTag.Order { + case earlyLibraryDependency: + panic(fmt.Errorf("early static libs not suppported")) + case normalLibraryDependency: + // static dependencies will be handled separately so they can be ordered + // using transitive dependencies. + ptr = nil + directStaticDeps = append(directStaticDeps, ccDep) + case lateLibraryDependency: + ptr = &depPaths.LateStaticLibs + default: + panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order)) } } } - if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRamdisk() && !c.InRecovery() { - // The vendor module is a no-vendor-variant VNDK library. Depend on the - // core module instead. - return libName - } else if c.UseVndk() && bothVendorAndCoreVariantsExist { - // The vendor module in Make will have been renamed to not conflict with the core - // module, so update the dependency name here accordingly. - return libName + c.getNameSuffixWithVndkVersion(ctx) - } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib { - return libName + vendorPublicLibrarySuffix - } else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() { - return libName + ramdiskSuffix - } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() { - return libName + recoverySuffix - } else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled { - return libName + nativeBridgeSuffix - } else { - return libName - } - } + if libDepTag.static() && !libDepTag.wholeStatic { + if !ccDep.CcLibraryInterface() || !ccDep.Static() { + ctx.ModuleErrorf("module %q not a static library", depName) + return + } - // Export the shared libs to Make. - switch depTag { - case SharedDepTag, sharedExportDepTag, lateSharedDepTag, earlySharedDepTag: - if ccDep.CcLibrary() { - if ccDep.BuildStubs() && android.InAnyApex(depName) { - // Add the dependency to the APEX(es) providing the library so that - // m can trigger building the APEXes as well. - for _, an := range android.GetApexesForModule(depName) { - c.Properties.ApexesProvidingSharedLibs = append( - c.Properties.ApexesProvidingSharedLibs, an) - } + // When combining coverage files for shared libraries and executables, coverage files + // in static libraries act as if they were whole static libraries. The same goes for + // source based Abi dump files. + if c, ok := ccDep.(*Module); ok { + staticLib := c.linker.(libraryInterface) + depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles, + staticLib.objs().coverageFiles...) + depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles, + staticLib.objs().sAbiDumpFiles...) + } else if c, ok := ccDep.(LinkableInterface); ok { + // Handle non-CC modules here + depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles, + c.CoverageFiles()...) } } - // Note: the order of libs in this list is not important because - // they merely serve as Make dependencies and do not affect this lib itself. - c.Properties.AndroidMkSharedLibs = append( - c.Properties.AndroidMkSharedLibs, makeLibName(depName)) - // Record baseLibName for snapshots. - c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, baseLibName(depName)) - case ndkStubDepTag, ndkLateStubDepTag: - c.Properties.AndroidMkSharedLibs = append( - c.Properties.AndroidMkSharedLibs, - depName+"."+ccDep.ApiLevel()) - case StaticDepTag, staticExportDepTag, lateStaticDepTag: - c.Properties.AndroidMkStaticLibs = append( - c.Properties.AndroidMkStaticLibs, makeLibName(depName)) - case runtimeDepTag: - c.Properties.AndroidMkRuntimeLibs = append( - c.Properties.AndroidMkRuntimeLibs, makeLibName(depName)) - // Record baseLibName for snapshots. - c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, baseLibName(depName)) - case wholeStaticDepTag: - c.Properties.AndroidMkWholeStaticLibs = append( - c.Properties.AndroidMkWholeStaticLibs, makeLibName(depName)) - case headerDepTag: - c.Properties.AndroidMkHeaderLibs = append( - c.Properties.AndroidMkHeaderLibs, makeLibName(depName)) + if ptr != nil { + if !linkFile.Valid() { + if !ctx.Config().AllowMissingDependencies() { + ctx.ModuleErrorf("module %q missing output file", depName) + } else { + ctx.AddMissingDependencies([]string{depName}) + } + return + } + *ptr = append(*ptr, linkFile.Path()) + } + + if depPtr != nil { + dep := depFile + if !dep.Valid() { + dep = linkFile + } + *depPtr = append(*depPtr, dep.Path()) + } + + makeLibName := c.makeLibName(ctx, ccDep, depName) + libDepTag.makeSuffix + switch { + case libDepTag.header(): + // TODO(ccross): The reexportFlags check is there to maintain previous + // behavior when adding libraryDependencyTag and should be removed. + if !libDepTag.reexportFlags { + c.Properties.AndroidMkHeaderLibs = append( + c.Properties.AndroidMkHeaderLibs, makeLibName) + } + case libDepTag.shared(): + if ccDep.CcLibrary() { + if ccDep.BuildStubs() && android.InAnyApex(depName) { + // Add the dependency to the APEX(es) providing the library so that + // m can trigger building the APEXes as well. + for _, an := range android.GetApexesForModule(depName) { + c.Properties.ApexesProvidingSharedLibs = append( + c.Properties.ApexesProvidingSharedLibs, an) + } + } + } + + // Note: the order of libs in this list is not important because + // they merely serve as Make dependencies and do not affect this lib itself. + // TODO(ccross): The reexportFlags, order and ndk checks are there to + // maintain previous behavior when adding libraryDependencyTag and + // should be removed. + if !c.static() || libDepTag.reexportFlags || libDepTag.Order == lateLibraryDependency || libDepTag.ndk { + c.Properties.AndroidMkSharedLibs = append( + c.Properties.AndroidMkSharedLibs, makeLibName) + } + // Record baseLibName for snapshots. + c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, baseLibName(depName)) + case libDepTag.static(): + if libDepTag.wholeStatic { + c.Properties.AndroidMkWholeStaticLibs = append( + c.Properties.AndroidMkWholeStaticLibs, makeLibName) + } else { + c.Properties.AndroidMkStaticLibs = append( + c.Properties.AndroidMkStaticLibs, makeLibName) + } + } + } else { + switch depTag { + case runtimeDepTag: + c.Properties.AndroidMkRuntimeLibs = append( + c.Properties.AndroidMkRuntimeLibs, c.makeLibName(ctx, ccDep, depName)+libDepTag.makeSuffix) + // Record baseLibName for snapshots. + c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, baseLibName(depName)) + case objDepTag: + depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path()) + case CrtBeginDepTag: + depPaths.CrtBegin = linkFile + case CrtEndDepTag: + depPaths.CrtEnd = linkFile + case dynamicLinkerDepTag: + depPaths.DynamicLinker = linkFile + } } }) @@ -2665,6 +2718,61 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return depPaths } +// baseLibName trims known prefixes and suffixes +func baseLibName(depName string) string { + libName := strings.TrimSuffix(depName, llndkLibrarySuffix) + libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix) + libName = strings.TrimPrefix(libName, "prebuilt_") + return libName +} + +func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, depName string) string { + vendorSuffixModules := vendorSuffixModules(ctx.Config()) + vendorPublicLibraries := vendorPublicLibraries(ctx.Config()) + + libName := baseLibName(depName) + isLLndk := isLlndkLibrary(libName, ctx.Config()) + isVendorPublicLib := inList(libName, *vendorPublicLibraries) + bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk + + if c, ok := ccDep.(*Module); ok { + // Use base module name for snapshots when exporting to Makefile. + if c.isSnapshotPrebuilt() { + baseName := c.BaseModuleName() + + if c.IsVndk() { + return baseName + ".vendor" + } + + if vendorSuffixModules[baseName] { + return baseName + ".vendor" + } else { + return baseName + } + } + } + + if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRamdisk() && !c.InRecovery() { + // The vendor module is a no-vendor-variant VNDK library. Depend on the + // core module instead. + return libName + } else if c.UseVndk() && bothVendorAndCoreVariantsExist { + // The vendor module in Make will have been renamed to not conflict with the core + // module, so update the dependency name here accordingly. + return libName + c.getNameSuffixWithVndkVersion(ctx) + } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib { + return libName + vendorPublicLibrarySuffix + } else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() { + return libName + ramdiskSuffix + } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() { + return libName + recoverySuffix + } else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled { + return libName + nativeBridgeSuffix + } else { + return libName + } +} + func (c *Module) InstallInData() bool { if c.installer == nil { return false @@ -2876,26 +2984,30 @@ func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Write } func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - if depTag, ok := ctx.OtherModuleDependencyTag(dep).(DependencyTag); ok { - if cc, ok := dep.(*Module); ok { - if cc.HasStubsVariants() { - if depTag.Shared && depTag.Library { - // dynamic dep to a stubs lib crosses APEX boundary - return false - } - if IsRuntimeDepTag(depTag) { - // runtime dep to a stubs lib also crosses APEX boundary - return false - } + depTag := ctx.OtherModuleDependencyTag(dep) + libDepTag, isLibDepTag := depTag.(libraryDependencyTag) + + if cc, ok := dep.(*Module); ok { + if cc.HasStubsVariants() { + if isLibDepTag && libDepTag.shared() { + // dynamic dep to a stubs lib crosses APEX boundary + return false } - if depTag.FromStatic { - // shared_lib dependency from a static lib is considered as crossing - // the APEX boundary because the dependency doesn't actually is - // linked; the dependency is used only during the compilation phase. + if IsRuntimeDepTag(depTag) { + // runtime dep to a stubs lib also crosses APEX boundary return false } } - } else if ctx.OtherModuleDependencyTag(dep) == llndkImplDep { + // TODO(ccross): The libDepTag.reexportFlags is there to maintain previous behavior + // when adding libraryDependencyTag and should be removed. + if isLibDepTag && c.static() && libDepTag.shared() && !libDepTag.reexportFlags { + // shared_lib dependency from a static lib is considered as crossing + // the APEX boundary because the dependency doesn't actually is + // linked; the dependency is used only during the compilation phase. + return false + } + } + if depTag == llndkImplDep { // We don't track beyond LLNDK return false } diff --git a/cc/coverage.go b/cc/coverage.go index c8233247f..1eac8a070 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -103,10 +103,14 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags // For static libraries, the only thing that changes our object files // are included whole static libraries, so check to see if any of // those have coverage enabled. - ctx.VisitDirectDepsWithTag(wholeStaticDepTag, func(m android.Module) { - if cc, ok := m.(*Module); ok && cc.coverage != nil { - if cc.coverage.linkCoverage { - cov.linkCoverage = true + ctx.VisitDirectDeps(func(m android.Module) { + if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok { + if depTag.static() && depTag.wholeStatic { + if cc, ok := m.(*Module); ok && cc.coverage != nil { + if cc.coverage.linkCoverage { + cov.linkCoverage = true + } + } } } }) diff --git a/cc/library.go b/cc/library.go index 98f4d48d6..2a329ac3c 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1633,8 +1633,7 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu // TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries. injectBoringSSLHash := Bool(inject) ctx.VisitDirectDeps(func(dep android.Module) { - tag := ctx.OtherModuleDependencyTag(dep) - if tag == StaticDepTag || tag == staticExportDepTag || tag == wholeStaticDepTag || tag == lateStaticDepTag { + if tag, ok := ctx.OtherModuleDependencyTag(dep).(libraryDependencyTag); ok && tag.static() { if cc, ok := dep.(*Module); ok { if library, ok := cc.linker.(*libraryDecorator); ok { if Bool(library.Properties.Inject_bssl_hash) { diff --git a/cc/linkable.go b/cc/linkable.go index 66b1c3fea..4c8416347 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -1,9 +1,9 @@ package cc import ( - "github.com/google/blueprint" - "android/soong/android" + + "github.com/google/blueprint" ) type LinkableInterface interface { @@ -63,27 +63,16 @@ type LinkableInterface interface { StubDecorator() bool } -type DependencyTag struct { - blueprint.BaseDependencyTag - Name string - Library bool - Shared bool +var ( + CrtBeginDepTag = dependencyTag{name: "crtbegin"} + CrtEndDepTag = dependencyTag{name: "crtend"} + CoverageDepTag = dependencyTag{name: "coverage"} +) - ReexportFlags bool - - ExplicitlyVersioned bool - - FromStatic bool +func SharedDepTag() blueprint.DependencyTag { + return libraryDependencyTag{Kind: sharedLibraryDependency} } -var ( - SharedDepTag = DependencyTag{Name: "shared", Library: true, Shared: true} - StaticDepTag = DependencyTag{Name: "static", Library: true} - - // Same as SharedDepTag, but from a static lib - SharedFromStaticDepTag = DependencyTag{Name: "shared from static", Library: true, Shared: true, FromStatic: true} - - CrtBeginDepTag = DependencyTag{Name: "crtbegin"} - CrtEndDepTag = DependencyTag{Name: "crtend"} - CoverageDepTag = DependencyTag{Name: "coverage"} -) +func StaticDepTag() blueprint.DependencyTag { + return libraryDependencyTag{Kind: staticLibraryDependency} +} diff --git a/cc/lto.go b/cc/lto.go index 4489fc7dd..ed3abe7ea 100644 --- a/cc/lto.go +++ b/cc/lto.go @@ -148,24 +148,33 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) { mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { tag := mctx.OtherModuleDependencyTag(dep) - switch tag { - case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag: - if dep, ok := dep.(*Module); ok && dep.lto != nil && - !dep.lto.Disabled() { - if full && !Bool(dep.lto.Properties.Lto.Full) { - dep.lto.Properties.FullDep = true - } - if thin && !Bool(dep.lto.Properties.Lto.Thin) { - dep.lto.Properties.ThinDep = true - } - } - - // Recursively walk static dependencies - return true - } + libTag, isLibTag := tag.(libraryDependencyTag) // Do not recurse down non-static dependencies - return false + if isLibTag { + // TODO(ccross): the staticUnwinder check is there to maintain existing behavior + // when adding libraryDependencyTag and should be removed. + if !libTag.static() || libTag.staticUnwinder { + return false + } + } else { + if tag != objDepTag && tag != reuseObjTag { + return false + } + } + + if dep, ok := dep.(*Module); ok && dep.lto != nil && + !dep.lto.Disabled() { + if full && !Bool(dep.lto.Properties.Lto.Full) { + dep.lto.Properties.FullDep = true + } + if thin && !Bool(dep.lto.Properties.Lto.Thin) { + dep.lto.Properties.ThinDep = true + } + } + + // Recursively walk static dependencies + return true }) } } diff --git a/cc/sabi.go b/cc/sabi.go index 8cef1700c..ef6beada6 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -83,10 +83,7 @@ func sabiDepsMutator(mctx android.TopDownMutatorContext) { ((c.IsVndk() && c.UseVndk()) || c.isLlndk(mctx.Config()) || (c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) { mctx.VisitDirectDeps(func(m android.Module) { - tag := mctx.OtherModuleDependencyTag(m) - switch tag { - case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag: - + if tag, ok := mctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok && tag.static() { cc, _ := m.(*Module) if cc == nil { return diff --git a/cc/sanitize.go b/cc/sanitize.go index 300bc8f7c..33e4a4abc 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -714,8 +714,14 @@ func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool { } func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool { - t, ok := tag.(DependencyTag) - return ok && t.Library || t == reuseObjTag || t == objDepTag + switch t := tag.(type) { + case dependencyTag: + return t == reuseObjTag || t == objDepTag + case libraryDependencyTag: + return true + default: + return false + } } // Propagate sanitizer requirements down from binaries @@ -957,10 +963,11 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { } // static executable gets static runtime libs + depTag := libraryDependencyTag{Kind: staticLibraryDependency} mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ {Mutator: "link", Variation: "static"}, c.ImageVariation(), - }...), StaticDepTag, deps...) + }...), depTag, deps...) } else if !c.static() && !c.header() { // If we're using snapshots and in vendor, redirect to snapshot whenever possible if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() { @@ -971,10 +978,11 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { } // dynamic executable and shared libs get shared runtime libs + depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: earlyLibraryDependency} mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ {Mutator: "link", Variation: "shared"}, c.ImageVariation(), - }...), earlySharedDepTag, runtimeLibrary) + }...), depTag, runtimeLibrary) } // static lib does not have dependency to the runtime library. The // dependency will be added to the executables or shared libs using diff --git a/cc/vndk.go b/cc/vndk.go index f9adec73a..23bb095bc 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -26,6 +26,8 @@ import ( "android/soong/android" "android/soong/cc/config" "android/soong/etc" + + "github.com/google/blueprint" ) const ( @@ -127,7 +129,7 @@ func (vndk *vndkdep) typeName() string { return "native:vendor:vndkspext" } -func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag DependencyTag) { +func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag blueprint.DependencyTag) { if to.linker == nil { return } diff --git a/java/app.go b/java/app.go index 4031cfeb1..44879182d 100755 --- a/java/app.go +++ b/java/app.go @@ -845,7 +845,9 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) - if IsJniDepTag(tag) || tag == cc.SharedDepTag { + // TODO(ccross): The tag == cc.SharedDepTag() check should be cc.IsSharedDepTag(tag) but + // was left to maintain behavior when adding libraryDependencyTag. + if IsJniDepTag(tag) || tag == cc.SharedDepTag() { if dep, ok := module.(*cc.Module); ok { if dep.IsNdk() || dep.IsStubs() { return false diff --git a/rust/rust.go b/rust/rust.go index 78bf7ada9..960f66a41 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -849,8 +849,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } exportDep := false - switch depTag { - case cc.StaticDepTag: + switch { + case cc.IsStaticDepTag(depTag): depFlag = "-lstatic=" + libName depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.depFlags = append(depPaths.depFlags, depFlag) @@ -862,7 +862,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...) directStaticLibDeps = append(directStaticLibDeps, ccDep) mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName) - case cc.SharedDepTag: + case cc.IsSharedDepTag(depTag): depFlag = "-ldylib=" + libName depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.depFlags = append(depPaths.depFlags, depFlag) @@ -874,9 +874,9 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directSharedLibDeps = append(directSharedLibDeps, ccDep) mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName) exportDep = true - case cc.CrtBeginDepTag: + case depTag == cc.CrtBeginDepTag: depPaths.CrtBegin = linkFile - case cc.CrtEndDepTag: + case depTag == cc.CrtEndDepTag: depPaths.CrtEnd = linkFile } @@ -994,10 +994,10 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { actx.AddVariationDependencies(append(commonDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), - cc.SharedDepTag, deps.SharedLibs...) + cc.SharedDepTag(), deps.SharedLibs...) actx.AddVariationDependencies(append(commonDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), - cc.StaticDepTag, deps.StaticLibs...) + cc.StaticDepTag(), deps.StaticLibs...) if deps.CrtBegin != "" { actx.AddVariationDependencies(commonDepVariations, cc.CrtBeginDepTag, deps.CrtBegin)