Convert sabi to TransitionMutator
The sabi mutator walks static dependencies of native libraries with ABI
stability guarantees (LLNDK, APEX, or cross-partition) and sets a flag
that causes the modules to generate additional rules to extract the ABI
from each source/object pair, combine them, and add a rule that diffs
them against the checked in version. In order to remove top down
mutators that mutate dependencies, convert it to a transition mutator.
This may cause the same static library code to be compiled identically
twice with and without the configuration, but there are relatively
few static libraries that are dependencies of stable ABI libraries.
If the cost of compiling these static libraries becomes too high this
can be replaced with something like Bazel aspects, where the stable
ABI library visits its static dependencies and adds extra rules to
generate the sabi dumps.
Bug: 367784740
Test: TestSabi
Flag: EXEMPT refactor
Change-Id: Ie6bd44680afdca15b09ba0b64ed0df9964a936a6
diff --git a/cc/sabi.go b/cc/sabi.go
index 64eab41..2caf0d4 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -84,8 +84,8 @@
type SAbiProperties struct {
// Whether ABI dump should be created for this module.
- // Set by `sabiDepsMutator` if this module is a shared library that needs ABI check, or a static
- // library that is depended on by an ABI checked library.
+ // Set by `sabiTransitionMutator` if this module is a shared library that needs ABI check,
+ // or a static library that is depended on by an ABI checked library.
ShouldCreateSourceAbiDump bool `blueprint:"mutated"`
// Include directories that may contain ABI information exported by a library.
@@ -121,10 +121,9 @@
}
// Returns a slice of strings that represent the ABI dumps generated for this module.
-func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag {
+func classifySourceAbiDump(m *Module) []lsdumpTag {
result := []lsdumpTag{}
- m := ctx.Module().(*Module)
- headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx)
+ headerAbiChecker := m.library.getHeaderAbiCheckerProperties(m)
if headerAbiChecker.explicitlyDisabled() {
return result
}
@@ -149,24 +148,37 @@
return result
}
-// Called from sabiDepsMutator to check whether ABI dumps should be created for this module.
+type shouldCreateAbiDumpContext interface {
+ android.ModuleProviderContext
+ Module() android.Module
+ Config() android.Config
+}
+
+var _ shouldCreateAbiDumpContext = android.ModuleContext(nil)
+var _ shouldCreateAbiDumpContext = android.OutgoingTransitionContext(nil)
+
+// Called from sabiTransitionMutator to check whether ABI dumps should be created for this module.
// ctx should be wrapping a native library type module.
-func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool {
- // Only generate ABI dump for device modules.
- if !ctx.Device() {
+func shouldCreateSourceAbiDumpForLibrary(ctx shouldCreateAbiDumpContext) bool {
+ m, ok := ctx.Module().(*Module)
+ if !ok {
return false
}
- m := ctx.Module().(*Module)
+ // Only generate ABI dump for device modules.
+ if !m.Device() {
+ return false
+ }
// Only create ABI dump for native library module types.
if m.library == nil {
return false
}
- // Create ABI dump for static libraries only if they are dependencies of ABI checked libraries.
+ // Don't create ABI dump for static libraries
+ // The sabi variant will be propagated to dependencies of ABI checked libraries.
if m.library.static() {
- return m.sabi.shouldCreateSourceAbiDump()
+ return false
}
// Module is shared library type.
@@ -215,31 +227,64 @@
return false
}
}
- return len(classifySourceAbiDump(ctx)) > 0
+ return len(classifySourceAbiDump(m)) > 0
}
// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps
// of their dependencies would be generated.
-func sabiDepsMutator(mctx android.TopDownMutatorContext) {
+type sabiTransitionMutator struct{}
+
+func (s *sabiTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{""}
+}
+
+func (s *sabiTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
// Escape hatch to not check any ABI dump.
- if mctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
- return
+ if ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
+ return ""
}
+
// Only create ABI dump for native shared libraries and their static library dependencies.
- if m, ok := mctx.Module().(*Module); ok && m.sabi != nil {
- if shouldCreateSourceAbiDumpForLibrary(mctx) {
- // Mark this module so that .sdump / .lsdump for this library can be generated.
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ if shouldCreateSourceAbiDumpForLibrary(ctx) {
+ if IsStaticDepTag(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
+ return "sabi"
+ }
+ } else if sourceVariation == "sabi" {
+ if IsWholeStaticLib(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
+ return "sabi"
+ }
+ }
+ }
+
+ return ""
+}
+
+func (s *sabiTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ if incomingVariation == "" {
+ return ""
+ }
+
+ if incomingVariation == "sabi" {
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ return "sabi"
+ }
+ }
+
+ return ""
+}
+
+func (s *sabiTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ if variation == "sabi" {
m.sabi.Properties.ShouldCreateSourceAbiDump = true
- // Mark all of its static library dependencies.
- mctx.VisitDirectDeps(func(child android.Module) {
- depTag := mctx.OtherModuleDependencyTag(child)
- if IsStaticDepTag(depTag) || depTag == reuseObjTag {
- if c, ok := child.(*Module); ok && c.sabi != nil {
- // Mark this module so that .sdump for this static library can be generated.
- c.sabi.Properties.ShouldCreateSourceAbiDump = true
- }
- }
- })
+ m.HideFromMake()
+ m.Properties.PreventInstall = true
+ } else if shouldCreateSourceAbiDumpForLibrary(ctx) {
+ // Escape hatch to not check any ABI dump.
+ if !ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
+ m.sabi.Properties.ShouldCreateSourceAbiDump = true
+ }
}
}
}