Merge "Add libraryDependencyTag to track dependencies on static and shared libraries"

This commit is contained in:
Colin Cross 2020-08-06 00:06:28 +00:00 committed by Gerrit Code Review
commit 2eddd06879
12 changed files with 465 additions and 343 deletions

View file

@ -1839,7 +1839,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.
@ -1850,7 +1850,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, "")

View file

@ -4450,11 +4450,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",

664
cc/cc.go
View file

@ -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 <module> 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 <module> 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
}

View file

@ -105,10 +105,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
}
}
}
}
})

View file

@ -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) {

View file

@ -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}
}

View file

@ -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
})
}
}

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -848,8 +848,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)
@ -861,7 +861,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)
@ -873,9 +873,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
}
@ -998,10 +998,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)