Merge changes I7b9462d3,Icadd470a,I1d459da1,I01d8f518

* changes:
  Add defaults_visibility support
  Refactor visibility to support visibility on defaults modules
  Add DefaultsModule interface
  Improve documentation of defaults mechanism
This commit is contained in:
Paul Duffin
2019-07-26 08:35:15 +00:00
committed by Gerrit Code Review
6 changed files with 155 additions and 43 deletions

View File

@@ -236,6 +236,11 @@ a `default_visibility` property is specified.
If no `default_visibility` property can be found then the module uses the If no `default_visibility` property can be found then the module uses the
global default of `//visibility:legacy_public`. global default of `//visibility:legacy_public`.
The `visibility` property has no effect on a defaults module although it does
apply to any non-defaults module that uses it. To set the visibility of a
defaults module, use the `defaults_visibility` property on the defaults module;
not to be confused with the `default_visibility` property on the package module.
Once the build has been completely switched over to soong it is possible that a Once the build has been completely switched over to soong it is possible that a
global refactoring will be done to change this to `//visibility:private` at global refactoring will be done to change this to `//visibility:private` at
which point all packages that do not currently specify a `default_visibility` which point all packages that do not currently specify a `default_visibility`

View File

@@ -42,9 +42,16 @@ func (d *DefaultableModuleBase) setProperties(props []interface{}) {
d.defaultableProperties = props d.defaultableProperties = props
} }
// Interface that must be supported by any module to which defaults can be applied.
type Defaultable interface { type Defaultable interface {
// Get a pointer to the struct containing the Defaults property.
defaults() *defaultsProperties defaults() *defaultsProperties
// Set the property structures into which defaults will be added.
setProperties([]interface{}) setProperties([]interface{})
// Apply defaults from the supplied Defaults to the property structures supplied to
// setProperties(...).
applyDefaults(TopDownMutatorContext, []Defaults) applyDefaults(TopDownMutatorContext, []Defaults)
} }
@@ -56,13 +63,25 @@ type DefaultableModule interface {
var _ Defaultable = (*DefaultableModuleBase)(nil) var _ Defaultable = (*DefaultableModuleBase)(nil)
func InitDefaultableModule(module DefaultableModule) { func InitDefaultableModule(module DefaultableModule) {
module.(Defaultable).setProperties(module.(Module).GetProperties()) module.setProperties(module.(Module).GetProperties())
module.AddProperties(module.defaults()) module.AddProperties(module.defaults())
} }
// The Defaults_visibility property.
type DefaultsVisibilityProperties struct {
// Controls the visibility of the defaults module itself.
Defaults_visibility []string
}
type DefaultsModuleBase struct { type DefaultsModuleBase struct {
DefaultableModuleBase DefaultableModuleBase
// Container for defaults of the common properties
commonProperties commonProperties
defaultsVisibilityProperties DefaultsVisibilityProperties
} }
// The common pattern for defaults modules is to register separate instances of // The common pattern for defaults modules is to register separate instances of
@@ -87,33 +106,75 @@ type DefaultsModuleBase struct {
// rather than disabling the defaults module itself. // rather than disabling the defaults module itself.
type Defaults interface { type Defaults interface {
Defaultable Defaultable
// Although this function is unused it is actually needed to ensure that only modules that embed
// DefaultsModuleBase will type-assert to the Defaults interface.
isDefaults() bool isDefaults() bool
// Get the structures containing the properties for which defaults can be provided.
properties() []interface{} properties() []interface{}
// Return the defaults common properties.
common() *commonProperties
// Return the defaults visibility properties.
defaultsVisibility() *DefaultsVisibilityProperties
} }
func (d *DefaultsModuleBase) isDefaults() bool { func (d *DefaultsModuleBase) isDefaults() bool {
return true return true
} }
type DefaultsModule interface {
Module
Defaults
}
func (d *DefaultsModuleBase) properties() []interface{} { func (d *DefaultsModuleBase) properties() []interface{} {
return d.defaultableProperties return d.defaultableProperties
} }
func (d *DefaultsModuleBase) common() *commonProperties {
return &d.commonProperties
}
func (d *DefaultsModuleBase) defaultsVisibility() *DefaultsVisibilityProperties {
return &d.defaultsVisibilityProperties
}
func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) { func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {
} }
func InitDefaultsModule(module DefaultableModule) { func InitDefaultsModule(module DefaultsModule) {
commonProperties := module.common()
module.AddProperties( module.AddProperties(
&hostAndDeviceProperties{}, &hostAndDeviceProperties{},
&commonProperties{}, commonProperties,
&variableProperties{}) &variableProperties{})
InitArchModule(module) InitArchModule(module)
InitDefaultableModule(module) InitDefaultableModule(module)
module.AddProperties(&module.base().nameProperties) // Add properties that will not have defaults applied to them.
base := module.base()
defaultsVisibility := module.defaultsVisibility()
module.AddProperties(&base.nameProperties, defaultsVisibility)
module.base().module = module // The defaults_visibility property controls the visibility of a defaults module.
base.primaryVisibilityProperty =
newVisibilityProperty("defaults_visibility", &defaultsVisibility.Defaults_visibility)
// Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
// Instead it is stored in a separate instance of commonProperties created above so use that.
// The visibility property needs to be checked (but not parsed) by the visibility module during
// its checking phase and parsing phase.
base.visibilityPropertyInfo = []visibilityProperty{
base.primaryVisibilityProperty,
newVisibilityProperty("visibility", &commonProperties.Visibility),
}
base.module = module
} }
var _ Defaults = (*DefaultsModuleBase)(nil) var _ Defaults = (*DefaultsModuleBase)(nil)

View File

@@ -211,6 +211,9 @@ type Module interface {
// Get information about the properties that can contain visibility rules. // Get information about the properties that can contain visibility rules.
visibilityProperties() []visibilityProperty visibilityProperties() []visibilityProperty
// Get the visibility rules that control the visibility of this module.
visibility() []string
} }
// Qualified id for a module // Qualified id for a module
@@ -302,6 +305,11 @@ type commonProperties struct {
// If no `default_visibility` property can be found then the module uses the // If no `default_visibility` property can be found then the module uses the
// global default of `//visibility:legacy_public`. // global default of `//visibility:legacy_public`.
// //
// The `visibility` property has no effect on a defaults module although it does
// apply to any non-defaults module that uses it. To set the visibility of a
// defaults module, use the `defaults_visibility` property on the defaults module;
// not to be confused with the `default_visibility` property on the package module.
//
// See https://android.googlesource.com/platform/build/soong/+/master/README.md#visibility for // See https://android.googlesource.com/platform/build/soong/+/master/README.md#visibility for
// more details. // more details.
Visibility []string Visibility []string
@@ -503,6 +511,12 @@ func InitAndroidModule(m Module) {
&base.variableProperties) &base.variableProperties)
base.generalProperties = m.GetProperties() base.generalProperties = m.GetProperties()
base.customizableProperties = m.GetProperties() base.customizableProperties = m.GetProperties()
// The default_visibility property needs to be checked and parsed by the visibility module during
// its checking and parsing phases.
base.primaryVisibilityProperty =
newVisibilityProperty("visibility", &base.commonProperties.Visibility)
base.visibilityPropertyInfo = []visibilityProperty{base.primaryVisibilityProperty}
} }
func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) { func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
@@ -582,6 +596,13 @@ type ModuleBase struct {
archProperties [][]interface{} archProperties [][]interface{}
customizableProperties []interface{} customizableProperties []interface{}
// Information about all the properties on the module that contains visibility rules that need
// checking.
visibilityPropertyInfo []visibilityProperty
// The primary visibility property, may be nil, that controls access to the module.
primaryVisibilityProperty visibilityProperty
noAddressSanitizer bool noAddressSanitizer bool
installFiles Paths installFiles Paths
checkbuildFiles Paths checkbuildFiles Paths
@@ -668,10 +689,15 @@ func (m *ModuleBase) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleNam
} }
func (m *ModuleBase) visibilityProperties() []visibilityProperty { func (m *ModuleBase) visibilityProperties() []visibilityProperty {
return []visibilityProperty{ return m.visibilityPropertyInfo
newVisibilityProperty("visibility", func() []string { }
return m.base().commonProperties.Visibility
}), func (m *ModuleBase) visibility() []string {
// The soong_namespace module does not initialize the primaryVisibilityProperty.
if m.primaryVisibilityProperty != nil {
return m.primaryVisibilityProperty.getStrings()
} else {
return nil
} }
} }

View File

@@ -64,16 +64,6 @@ func (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModule
return newPackageId(ctx.ModuleDir()) return newPackageId(ctx.ModuleDir())
} }
// Override to ensure that the default_visibility rules are checked by the visibility module during
// its checking phase.
func (p *packageModule) visibilityProperties() []visibilityProperty {
return []visibilityProperty{
newVisibilityProperty("default_visibility", func() []string {
return p.properties.Default_visibility
}),
}
}
func (p *packageModule) Name() string { func (p *packageModule) Name() string {
return p.properties.Name return p.properties.Name
} }
@@ -97,6 +87,13 @@ func PackageFactory() Module {
module.properties.Name = name module.properties.Name = name
module.AddProperties(&module.properties) module.AddProperties(&module.properties)
// The default_visibility property needs to be checked and parsed by the visibility module during
// its checking and parsing phases.
module.primaryVisibilityProperty =
newVisibilityProperty("default_visibility", &module.properties.Default_visibility)
module.visibilityPropertyInfo = []visibilityProperty{module.primaryVisibilityProperty}
return module return module
} }

View File

@@ -68,7 +68,7 @@ type visibilityRule interface {
// Describes the properties provided by a module that contain visibility rules. // Describes the properties provided by a module that contain visibility rules.
type visibilityPropertyImpl struct { type visibilityPropertyImpl struct {
name string name string
stringsGetter func() []string stringsProperty *[]string
} }
type visibilityProperty interface { type visibilityProperty interface {
@@ -76,10 +76,10 @@ type visibilityProperty interface {
getStrings() []string getStrings() []string
} }
func newVisibilityProperty(name string, stringsGetter func() []string) visibilityProperty { func newVisibilityProperty(name string, stringsProperty *[]string) visibilityProperty {
return visibilityPropertyImpl{ return visibilityPropertyImpl{
name: name, name: name,
stringsGetter: stringsGetter, stringsProperty: stringsProperty,
} }
} }
@@ -88,7 +88,7 @@ func (p visibilityPropertyImpl) getName() string {
} }
func (p visibilityPropertyImpl) getStrings() []string { func (p visibilityPropertyImpl) getStrings() []string {
return p.stringsGetter() return *p.stringsProperty
} }
// A compositeRule is a visibility rule composed from a list of atomic visibility rules. // A compositeRule is a visibility rule composed from a list of atomic visibility rules.
@@ -211,16 +211,7 @@ func registerVisibilityRuleEnforcer(ctx RegisterMutatorsContext) {
// Checks the per-module visibility rule lists before defaults expansion. // Checks the per-module visibility rule lists before defaults expansion.
func visibilityRuleChecker(ctx BottomUpMutatorContext) { func visibilityRuleChecker(ctx BottomUpMutatorContext) {
qualified := createQualifiedModuleName(ctx) qualified := createQualifiedModuleName(ctx)
if d, ok := ctx.Module().(Defaults); ok { if m, ok := ctx.Module().(Module); ok {
// Defaults modules don't store the payload properties in m.base().
for _, props := range d.properties() {
if cp, ok := props.(*commonProperties); ok {
if visibility := cp.Visibility; visibility != nil {
checkRules(ctx, qualified.pkg, "visibility", visibility)
}
}
}
} else if m, ok := ctx.Module().(Module); ok {
visibilityProperties := m.visibilityProperties() visibilityProperties := m.visibilityProperties()
for _, p := range visibilityProperties { for _, p := range visibilityProperties {
if visibility := p.getStrings(); visibility != nil { if visibility := p.getStrings(); visibility != nil {
@@ -294,17 +285,15 @@ func visibilityRuleGatherer(ctx BottomUpMutatorContext) {
qualifiedModuleId := m.qualifiedModuleId(ctx) qualifiedModuleId := m.qualifiedModuleId(ctx)
currentPkg := qualifiedModuleId.pkg currentPkg := qualifiedModuleId.pkg
// Parse all the properties into rules and store them. // Parse the visibility rules that control access to the module and store them by id
visibilityProperties := m.visibilityProperties() // for use when enforcing the rules.
for _, p := range visibilityProperties { if visibility := m.visibility(); visibility != nil {
if visibility := p.getStrings(); visibility != nil { rule := parseRules(ctx, currentPkg, m.visibility())
rule := parseRules(ctx, currentPkg, visibility)
if rule != nil { if rule != nil {
moduleToVisibilityRuleMap(ctx).Store(qualifiedModuleId, rule) moduleToVisibilityRuleMap(ctx).Store(qualifiedModuleId, rule)
} }
} }
} }
}
func parseRules(ctx BaseModuleContext, currentPkg string, visibility []string) compositeRule { func parseRules(ctx BaseModuleContext, currentPkg string, visibility []string) compositeRule {
rules := make(compositeRule, 0, len(visibility)) rules := make(compositeRule, 0, len(visibility))

View File

@@ -658,6 +658,40 @@ var visibilityTests = []struct {
` visible to this module`, ` visible to this module`,
}, },
}, },
// Defaults module's defaults_visibility tests
{
name: "defaults_visibility invalid",
fs: map[string][]byte{
"top/Blueprints": []byte(`
mock_defaults {
name: "top_defaults",
defaults_visibility: ["//visibility:invalid"],
}`),
},
expectedErrors: []string{
`defaults_visibility: unrecognized visibility rule "//visibility:invalid"`,
},
},
{
name: "defaults_visibility overrides package default",
fs: map[string][]byte{
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:private"],
}
mock_defaults {
name: "top_defaults",
defaults_visibility: ["//visibility:public"],
}`),
"outsider/Blueprints": []byte(`
mock_library {
name: "liboutsider",
defaults: ["top_defaults"],
}`),
},
},
// Package default_visibility tests // Package default_visibility tests
{ {
name: "package default_visibility property is checked", name: "package default_visibility property is checked",