Avoid Rust source provider rule duplication
Until now, source provider modules duplicated the rule to generate the
source for each variant. Add a inter-variant dependency between the
source and the other variants (e.g. rlib, dylib) to avoid this
duplication. Add documentation on this behaviour.
Bug: 162588681
Test: m
Change-Id: I41c9e2220f8875245415e17374852e540dfd47ec
diff --git a/rust/library.go b/rust/library.go
index 4931f19..2792c5b 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -15,6 +15,7 @@
package rust
import (
+ "fmt"
"regexp"
"strings"
@@ -77,6 +78,8 @@
VariantIsShared bool `blueprint:"mutated"`
// This variant is a static library
VariantIsStatic bool `blueprint:"mutated"`
+ // This variant is a source provider
+ VariantIsSource bool `blueprint:"mutated"`
// This variant is disabled and should not be compiled
// (used for SourceProvider variants that produce only source)
@@ -103,6 +106,7 @@
static() bool
shared() bool
sysroot() bool
+ source() bool
// Returns true if the build options for the module have selected a particular build type
buildRlib() bool
@@ -115,6 +119,7 @@
setDylib()
setShared()
setStatic()
+ setSource()
// Set libstd linkage
setRlibStd()
@@ -158,6 +163,10 @@
return library.static() || library.MutatedProperties.VariantIsStaticStd
}
+func (library *libraryDecorator) source() bool {
+ return library.MutatedProperties.VariantIsSource
+}
+
func (library *libraryDecorator) buildRlib() bool {
return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true)
}
@@ -210,13 +219,17 @@
library.MutatedProperties.VariantIsDylib = false
}
+func (library *libraryDecorator) setSource() {
+ library.MutatedProperties.VariantIsSource = true
+}
+
func (library *libraryDecorator) autoDep(ctx BaseModuleContext) autoDep {
if library.rlib() || library.static() {
return rlibAutoDep
} else if library.dylib() || library.shared() {
return dylibAutoDep
} else {
- panic("autoDep called on library" + ctx.ModuleName() + "that has no enabled variants.")
+ panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName()))
}
}
@@ -518,41 +531,68 @@
}
}
+// LibraryMutator mutates the libraries into variants according to the
+// build{Rlib,Dylib} attributes.
func LibraryMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok && m.compiler != nil {
- switch library := m.compiler.(type) {
- case libraryInterface:
- if library.buildRlib() && library.buildDylib() {
- variants := []string{"rlib", "dylib"}
- if m.sourceProvider != nil {
- variants = append(variants, "")
- }
- modules := mctx.CreateLocalVariations(variants...)
+ // Only mutate on Rust libraries.
+ m, ok := mctx.Module().(*Module)
+ if !ok || m.compiler == nil {
+ return
+ }
+ library, ok := m.compiler.(libraryInterface)
+ if !ok {
+ return
+ }
- rlib := modules[0].(*Module)
- dylib := modules[1].(*Module)
- rlib.compiler.(libraryInterface).setRlib()
- dylib.compiler.(libraryInterface).setDylib()
- if m.sourceProvider != nil {
- // This library is SourceProvider generated, so the non-library-producing
- // variant needs to disable it's compiler and skip installation.
- sourceProvider := modules[2].(*Module)
- sourceProvider.compiler.SetDisabled()
- }
- } else if library.buildRlib() {
- modules := mctx.CreateLocalVariations("rlib")
- modules[0].(*Module).compiler.(libraryInterface).setRlib()
- } else if library.buildDylib() {
- modules := mctx.CreateLocalVariations("dylib")
- modules[0].(*Module).compiler.(libraryInterface).setDylib()
- }
+ var variants []string
+ // The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib)
+ // depend on this variant. It must be the first variant to be declared.
+ sourceVariant := false
+ if m.sourceProvider != nil {
+ variants = append(variants, "source")
+ sourceVariant = true
+ }
+ if library.buildRlib() {
+ variants = append(variants, rlibVariation)
+ }
+ if library.buildDylib() {
+ variants = append(variants, dylibVariation)
+ }
- if m.sourceProvider != nil {
- // Alias the non-library variant to the empty-string variant.
- mctx.AliasVariation("")
- }
+ if len(variants) == 0 {
+ return
+ }
+ modules := mctx.CreateLocalVariations(variants...)
+
+ // The order of the variations (modules) matches the variant names provided. Iterate
+ // through the new variation modules and set their mutated properties.
+ for i, v := range modules {
+ switch variants[i] {
+ case rlibVariation:
+ v.(*Module).compiler.(libraryInterface).setRlib()
+ case dylibVariation:
+ v.(*Module).compiler.(libraryInterface).setDylib()
+ case "source":
+ v.(*Module).compiler.(libraryInterface).setSource()
+ // The source variant does not produce any library.
+ // Disable the compilation steps.
+ v.(*Module).compiler.SetDisabled()
}
}
+
+ // If a source variant is created, add an inter-variant dependency
+ // between the other variants and the source variant.
+ if sourceVariant {
+ sv := modules[0]
+ for _, v := range modules[1:] {
+ if !v.Enabled() {
+ continue
+ }
+ mctx.AddInterVariantDependency(sourceDepTag, v, sv)
+ }
+ // Alias the source variation so it can be named directly in "srcs" properties.
+ mctx.AliasVariation("source")
+ }
}
func LibstdMutator(mctx android.BottomUpMutatorContext) {