1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage android 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "regexp" 20*333d2b36SAndroid Build Coastguard Worker "sort" 21*333d2b36SAndroid Build Coastguard Worker "strings" 22*333d2b36SAndroid Build Coastguard Worker "sync" 23*333d2b36SAndroid Build Coastguard Worker 24*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 25*333d2b36SAndroid Build Coastguard Worker) 26*333d2b36SAndroid Build Coastguard Worker 27*333d2b36SAndroid Build Coastguard Worker// Enforces visibility rules between modules. 28*333d2b36SAndroid Build Coastguard Worker// 29*333d2b36SAndroid Build Coastguard Worker// Multi stage process: 30*333d2b36SAndroid Build Coastguard Worker// * First stage works bottom up, before defaults expansion, to check the syntax of the visibility 31*333d2b36SAndroid Build Coastguard Worker// rules that have been specified. 32*333d2b36SAndroid Build Coastguard Worker// 33*333d2b36SAndroid Build Coastguard Worker// * Second stage works bottom up to extract the package info for each package and store them in a 34*333d2b36SAndroid Build Coastguard Worker// map by package name. See package.go for functionality for this. 35*333d2b36SAndroid Build Coastguard Worker// 36*333d2b36SAndroid Build Coastguard Worker// * Third stage works bottom up to extract visibility information from the modules, parse it, 37*333d2b36SAndroid Build Coastguard Worker// create visibilityRule structures and store them in a map keyed by the module's 38*333d2b36SAndroid Build Coastguard Worker// qualifiedModuleName instance, i.e. //<pkg>:<name>. The map is stored in the context rather 39*333d2b36SAndroid Build Coastguard Worker// than a global variable for testing. Each test has its own Config so they do not share a map 40*333d2b36SAndroid Build Coastguard Worker// and so can be run in parallel. If a module has no visibility specified then it uses the 41*333d2b36SAndroid Build Coastguard Worker// default package visibility if specified. 42*333d2b36SAndroid Build Coastguard Worker// 43*333d2b36SAndroid Build Coastguard Worker// * Fourth stage works top down and iterates over all the deps for each module. If the dep is in 44*333d2b36SAndroid Build Coastguard Worker// the same package then it is automatically visible. Otherwise, for each dep it first extracts 45*333d2b36SAndroid Build Coastguard Worker// its visibilityRule from the config map. If one could not be found then it assumes that it is 46*333d2b36SAndroid Build Coastguard Worker// publicly visible. Otherwise, it calls the visibility rule to check that the module can see 47*333d2b36SAndroid Build Coastguard Worker// the dependency. If it cannot then an error is reported. 48*333d2b36SAndroid Build Coastguard Worker// 49*333d2b36SAndroid Build Coastguard Worker// TODO(b/130631145) - Make visibility work properly with prebuilts. 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Worker// Patterns for the values that can be specified in visibility property. 52*333d2b36SAndroid Build Coastguard Workerconst ( 53*333d2b36SAndroid Build Coastguard Worker packagePattern = `//([^/:]+(?:/[^/:]+)*)` 54*333d2b36SAndroid Build Coastguard Worker namePattern = `:([^/:]+)` 55*333d2b36SAndroid Build Coastguard Worker visibilityRulePattern = `^(?:` + packagePattern + `)?(?:` + namePattern + `)?$` 56*333d2b36SAndroid Build Coastguard Worker) 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Workervar visibilityRuleRegexp = regexp.MustCompile(visibilityRulePattern) 59*333d2b36SAndroid Build Coastguard Worker 60*333d2b36SAndroid Build Coastguard Workertype visibilityModuleReference struct { 61*333d2b36SAndroid Build Coastguard Worker name qualifiedModuleName 62*333d2b36SAndroid Build Coastguard Worker module Module 63*333d2b36SAndroid Build Coastguard Worker} 64*333d2b36SAndroid Build Coastguard Worker 65*333d2b36SAndroid Build Coastguard Workerfunc createVisibilityModuleReference(name, dir string, module Module) visibilityModuleReference { 66*333d2b36SAndroid Build Coastguard Worker return visibilityModuleReference{ 67*333d2b36SAndroid Build Coastguard Worker name: createQualifiedModuleName(name, dir), 68*333d2b36SAndroid Build Coastguard Worker module: module, 69*333d2b36SAndroid Build Coastguard Worker } 70*333d2b36SAndroid Build Coastguard Worker} 71*333d2b36SAndroid Build Coastguard Worker 72*333d2b36SAndroid Build Coastguard Worker// A visibility rule is associated with a module and determines which other modules it is visible 73*333d2b36SAndroid Build Coastguard Worker// to, i.e. which other modules can depend on the rule's module. 74*333d2b36SAndroid Build Coastguard Workertype visibilityRule interface { 75*333d2b36SAndroid Build Coastguard Worker // Check to see whether this rules matches m. 76*333d2b36SAndroid Build Coastguard Worker // Returns true if it does, false otherwise. 77*333d2b36SAndroid Build Coastguard Worker matches(m visibilityModuleReference) bool 78*333d2b36SAndroid Build Coastguard Worker 79*333d2b36SAndroid Build Coastguard Worker String() string 80*333d2b36SAndroid Build Coastguard Worker} 81*333d2b36SAndroid Build Coastguard Worker 82*333d2b36SAndroid Build Coastguard Worker// Describes the properties provided by a module that contain visibility rules. 83*333d2b36SAndroid Build Coastguard Workertype visibilityPropertyImpl struct { 84*333d2b36SAndroid Build Coastguard Worker name string 85*333d2b36SAndroid Build Coastguard Worker stringsProperty *[]string 86*333d2b36SAndroid Build Coastguard Worker} 87*333d2b36SAndroid Build Coastguard Worker 88*333d2b36SAndroid Build Coastguard Workertype visibilityProperty interface { 89*333d2b36SAndroid Build Coastguard Worker getName() string 90*333d2b36SAndroid Build Coastguard Worker getStrings() []string 91*333d2b36SAndroid Build Coastguard Worker} 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Workerfunc newVisibilityProperty(name string, stringsProperty *[]string) visibilityProperty { 94*333d2b36SAndroid Build Coastguard Worker return visibilityPropertyImpl{ 95*333d2b36SAndroid Build Coastguard Worker name: name, 96*333d2b36SAndroid Build Coastguard Worker stringsProperty: stringsProperty, 97*333d2b36SAndroid Build Coastguard Worker } 98*333d2b36SAndroid Build Coastguard Worker} 99*333d2b36SAndroid Build Coastguard Worker 100*333d2b36SAndroid Build Coastguard Workerfunc (p visibilityPropertyImpl) getName() string { 101*333d2b36SAndroid Build Coastguard Worker return p.name 102*333d2b36SAndroid Build Coastguard Worker} 103*333d2b36SAndroid Build Coastguard Worker 104*333d2b36SAndroid Build Coastguard Workerfunc (p visibilityPropertyImpl) getStrings() []string { 105*333d2b36SAndroid Build Coastguard Worker return *p.stringsProperty 106*333d2b36SAndroid Build Coastguard Worker} 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Worker// A compositeRule is a visibility rule composed from a list of atomic visibility rules. 109*333d2b36SAndroid Build Coastguard Worker// 110*333d2b36SAndroid Build Coastguard Worker// The list corresponds to the list of strings in the visibility property after defaults expansion. 111*333d2b36SAndroid Build Coastguard Worker// Even though //visibility:public is not allowed together with other rules in the visibility list 112*333d2b36SAndroid Build Coastguard Worker// of a single module, it is allowed here to permit a module to override an inherited visibility 113*333d2b36SAndroid Build Coastguard Worker// spec with public visibility. 114*333d2b36SAndroid Build Coastguard Worker// 115*333d2b36SAndroid Build Coastguard Worker// //visibility:private is not allowed in the same way, since we'd need to check for it during the 116*333d2b36SAndroid Build Coastguard Worker// defaults expansion to make that work. No non-private visibility rules are allowed in a 117*333d2b36SAndroid Build Coastguard Worker// compositeRule containing a privateRule. 118*333d2b36SAndroid Build Coastguard Worker// 119*333d2b36SAndroid Build Coastguard Worker// This array will only be [] if all the rules are invalid and will behave as if visibility was 120*333d2b36SAndroid Build Coastguard Worker// ["//visibility:private"]. 121*333d2b36SAndroid Build Coastguard Workertype compositeRule []visibilityRule 122*333d2b36SAndroid Build Coastguard Worker 123*333d2b36SAndroid Build Coastguard Workervar _ visibilityRule = compositeRule{} 124*333d2b36SAndroid Build Coastguard Worker 125*333d2b36SAndroid Build Coastguard Worker// A compositeRule matches if and only if any of its rules matches. 126*333d2b36SAndroid Build Coastguard Workerfunc (c compositeRule) matches(m visibilityModuleReference) bool { 127*333d2b36SAndroid Build Coastguard Worker for _, r := range c { 128*333d2b36SAndroid Build Coastguard Worker if r.matches(m) { 129*333d2b36SAndroid Build Coastguard Worker return true 130*333d2b36SAndroid Build Coastguard Worker } 131*333d2b36SAndroid Build Coastguard Worker } 132*333d2b36SAndroid Build Coastguard Worker return false 133*333d2b36SAndroid Build Coastguard Worker} 134*333d2b36SAndroid Build Coastguard Worker 135*333d2b36SAndroid Build Coastguard Workerfunc (c compositeRule) String() string { 136*333d2b36SAndroid Build Coastguard Worker return "[" + strings.Join(c.Strings(), ", ") + "]" 137*333d2b36SAndroid Build Coastguard Worker} 138*333d2b36SAndroid Build Coastguard Worker 139*333d2b36SAndroid Build Coastguard Workerfunc (c compositeRule) Strings() []string { 140*333d2b36SAndroid Build Coastguard Worker s := make([]string, 0, len(c)) 141*333d2b36SAndroid Build Coastguard Worker for _, r := range c { 142*333d2b36SAndroid Build Coastguard Worker s = append(s, r.String()) 143*333d2b36SAndroid Build Coastguard Worker } 144*333d2b36SAndroid Build Coastguard Worker return s 145*333d2b36SAndroid Build Coastguard Worker} 146*333d2b36SAndroid Build Coastguard Worker 147*333d2b36SAndroid Build Coastguard Worker// A packageRule is a visibility rule that matches modules in a specific package (i.e. directory). 148*333d2b36SAndroid Build Coastguard Workertype packageRule struct { 149*333d2b36SAndroid Build Coastguard Worker pkg string 150*333d2b36SAndroid Build Coastguard Worker} 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Workervar _ visibilityRule = packageRule{} 153*333d2b36SAndroid Build Coastguard Worker 154*333d2b36SAndroid Build Coastguard Workerfunc (r packageRule) matches(m visibilityModuleReference) bool { 155*333d2b36SAndroid Build Coastguard Worker return m.name.pkg == r.pkg 156*333d2b36SAndroid Build Coastguard Worker} 157*333d2b36SAndroid Build Coastguard Worker 158*333d2b36SAndroid Build Coastguard Workerfunc (r packageRule) String() string { 159*333d2b36SAndroid Build Coastguard Worker return fmt.Sprintf("//%s", r.pkg) // :__pkg__ is the default, so skip it. 160*333d2b36SAndroid Build Coastguard Worker} 161*333d2b36SAndroid Build Coastguard Worker 162*333d2b36SAndroid Build Coastguard Worker// A subpackagesRule is a visibility rule that matches modules in a specific package (i.e. 163*333d2b36SAndroid Build Coastguard Worker// directory) or any of its subpackages (i.e. subdirectories). 164*333d2b36SAndroid Build Coastguard Workertype subpackagesRule struct { 165*333d2b36SAndroid Build Coastguard Worker pkgPrefix string 166*333d2b36SAndroid Build Coastguard Worker} 167*333d2b36SAndroid Build Coastguard Worker 168*333d2b36SAndroid Build Coastguard Workervar _ visibilityRule = subpackagesRule{} 169*333d2b36SAndroid Build Coastguard Worker 170*333d2b36SAndroid Build Coastguard Workerfunc (r subpackagesRule) matches(m visibilityModuleReference) bool { 171*333d2b36SAndroid Build Coastguard Worker return isAncestor(r.pkgPrefix, m.name.pkg) 172*333d2b36SAndroid Build Coastguard Worker} 173*333d2b36SAndroid Build Coastguard Worker 174*333d2b36SAndroid Build Coastguard Workerfunc isAncestor(p1 string, p2 string) bool { 175*333d2b36SAndroid Build Coastguard Worker // Equivalent to strings.HasPrefix(p2+"/", p1+"/"), but without the string copies 176*333d2b36SAndroid Build Coastguard Worker // The check for a trailing slash is so that we don't consider sibling 177*333d2b36SAndroid Build Coastguard Worker // directories with common prefixes to be ancestors, e.g. "fooo/bar" should not be 178*333d2b36SAndroid Build Coastguard Worker // a descendant of "foo". 179*333d2b36SAndroid Build Coastguard Worker return strings.HasPrefix(p2, p1) && (len(p2) == len(p1) || p2[len(p1)] == '/') 180*333d2b36SAndroid Build Coastguard Worker} 181*333d2b36SAndroid Build Coastguard Worker 182*333d2b36SAndroid Build Coastguard Workerfunc (r subpackagesRule) String() string { 183*333d2b36SAndroid Build Coastguard Worker return fmt.Sprintf("//%s:__subpackages__", r.pkgPrefix) 184*333d2b36SAndroid Build Coastguard Worker} 185*333d2b36SAndroid Build Coastguard Worker 186*333d2b36SAndroid Build Coastguard Worker// visibilityRule for //visibility:public 187*333d2b36SAndroid Build Coastguard Workertype publicRule struct{} 188*333d2b36SAndroid Build Coastguard Worker 189*333d2b36SAndroid Build Coastguard Workervar _ visibilityRule = publicRule{} 190*333d2b36SAndroid Build Coastguard Worker 191*333d2b36SAndroid Build Coastguard Workerfunc (r publicRule) matches(_ visibilityModuleReference) bool { 192*333d2b36SAndroid Build Coastguard Worker return true 193*333d2b36SAndroid Build Coastguard Worker} 194*333d2b36SAndroid Build Coastguard Worker 195*333d2b36SAndroid Build Coastguard Workerfunc (r publicRule) String() string { 196*333d2b36SAndroid Build Coastguard Worker return "//visibility:public" 197*333d2b36SAndroid Build Coastguard Worker} 198*333d2b36SAndroid Build Coastguard Worker 199*333d2b36SAndroid Build Coastguard Worker// visibilityRule for //visibility:private 200*333d2b36SAndroid Build Coastguard Workertype privateRule struct{} 201*333d2b36SAndroid Build Coastguard Worker 202*333d2b36SAndroid Build Coastguard Workervar _ visibilityRule = privateRule{} 203*333d2b36SAndroid Build Coastguard Worker 204*333d2b36SAndroid Build Coastguard Workerfunc (r privateRule) matches(_ visibilityModuleReference) bool { 205*333d2b36SAndroid Build Coastguard Worker return false 206*333d2b36SAndroid Build Coastguard Worker} 207*333d2b36SAndroid Build Coastguard Worker 208*333d2b36SAndroid Build Coastguard Workerfunc (r privateRule) String() string { 209*333d2b36SAndroid Build Coastguard Worker return "//visibility:private" 210*333d2b36SAndroid Build Coastguard Worker} 211*333d2b36SAndroid Build Coastguard Worker 212*333d2b36SAndroid Build Coastguard Workervar anyPartitionRegex = regexp.MustCompile("^any_(system|system_ext|vendor|product|data|odm)_partition$") 213*333d2b36SAndroid Build Coastguard Worker 214*333d2b36SAndroid Build Coastguard Worker// visibilityRule for //visibility:any_partition 215*333d2b36SAndroid Build Coastguard Workertype anyPartitionRule struct { 216*333d2b36SAndroid Build Coastguard Worker partitionType string 217*333d2b36SAndroid Build Coastguard Worker} 218*333d2b36SAndroid Build Coastguard Worker 219*333d2b36SAndroid Build Coastguard Workervar _ visibilityRule = anyPartitionRule{} 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Workertype PartitionTypeInterface interface { 222*333d2b36SAndroid Build Coastguard Worker PartitionType() string 223*333d2b36SAndroid Build Coastguard Worker} 224*333d2b36SAndroid Build Coastguard Worker 225*333d2b36SAndroid Build Coastguard Workerfunc (r anyPartitionRule) matches(m visibilityModuleReference) bool { 226*333d2b36SAndroid Build Coastguard Worker if m2, ok := m.module.(PartitionTypeInterface); ok { 227*333d2b36SAndroid Build Coastguard Worker return m2.PartitionType() == r.partitionType 228*333d2b36SAndroid Build Coastguard Worker } 229*333d2b36SAndroid Build Coastguard Worker return false 230*333d2b36SAndroid Build Coastguard Worker} 231*333d2b36SAndroid Build Coastguard Worker 232*333d2b36SAndroid Build Coastguard Workerfunc (r anyPartitionRule) String() string { 233*333d2b36SAndroid Build Coastguard Worker return "//visibility:any_" + r.partitionType + "_partition" 234*333d2b36SAndroid Build Coastguard Worker} 235*333d2b36SAndroid Build Coastguard Worker 236*333d2b36SAndroid Build Coastguard Workervar visibilityRuleMap = NewOnceKey("visibilityRuleMap") 237*333d2b36SAndroid Build Coastguard Worker 238*333d2b36SAndroid Build Coastguard Workertype visibilityRulesForModule struct { 239*333d2b36SAndroid Build Coastguard Worker rule compositeRule 240*333d2b36SAndroid Build Coastguard Worker implicitPartitionRules compositeRule 241*333d2b36SAndroid Build Coastguard Worker} 242*333d2b36SAndroid Build Coastguard Worker 243*333d2b36SAndroid Build Coastguard Worker// The map from qualifiedModuleName to visibilityRule. 244*333d2b36SAndroid Build Coastguard Workerfunc moduleToVisibilityRuleMap(config Config) *sync.Map { 245*333d2b36SAndroid Build Coastguard Worker return config.Once(visibilityRuleMap, func() interface{} { 246*333d2b36SAndroid Build Coastguard Worker return &sync.Map{} 247*333d2b36SAndroid Build Coastguard Worker }).(*sync.Map) 248*333d2b36SAndroid Build Coastguard Worker} 249*333d2b36SAndroid Build Coastguard Worker 250*333d2b36SAndroid Build Coastguard Worker// Marker interface that identifies dependencies that are excluded from visibility 251*333d2b36SAndroid Build Coastguard Worker// enforcement. 252*333d2b36SAndroid Build Coastguard Workertype ExcludeFromVisibilityEnforcementTag interface { 253*333d2b36SAndroid Build Coastguard Worker blueprint.DependencyTag 254*333d2b36SAndroid Build Coastguard Worker 255*333d2b36SAndroid Build Coastguard Worker // Method that differentiates this interface from others. 256*333d2b36SAndroid Build Coastguard Worker ExcludeFromVisibilityEnforcement() 257*333d2b36SAndroid Build Coastguard Worker} 258*333d2b36SAndroid Build Coastguard Worker 259*333d2b36SAndroid Build Coastguard Worker// The visibility mutators. 260*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithVisibility = FixtureRegisterWithContext(registerVisibilityMutators) 261*333d2b36SAndroid Build Coastguard Worker 262*333d2b36SAndroid Build Coastguard Workerfunc registerVisibilityMutators(ctx RegistrationContext) { 263*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterVisibilityRuleChecker) 264*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterVisibilityRuleGatherer) 265*333d2b36SAndroid Build Coastguard Worker ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) 266*333d2b36SAndroid Build Coastguard Worker} 267*333d2b36SAndroid Build Coastguard Worker 268*333d2b36SAndroid Build Coastguard Worker// The rule checker needs to be registered before defaults expansion to correctly check that 269*333d2b36SAndroid Build Coastguard Worker// //visibility:xxx isn't combined with other packages in the same list in any one module. 270*333d2b36SAndroid Build Coastguard Workerfunc RegisterVisibilityRuleChecker(ctx RegisterMutatorsContext) { 271*333d2b36SAndroid Build Coastguard Worker ctx.BottomUp("visibilityRuleChecker", visibilityRuleChecker) 272*333d2b36SAndroid Build Coastguard Worker} 273*333d2b36SAndroid Build Coastguard Worker 274*333d2b36SAndroid Build Coastguard Worker// Registers the function that gathers the visibility rules for each module. 275*333d2b36SAndroid Build Coastguard Worker// 276*333d2b36SAndroid Build Coastguard Worker// Visibility is not dependent on arch so this must be registered before the arch phase to avoid 277*333d2b36SAndroid Build Coastguard Worker// having to process multiple variants for each module. This goes after defaults expansion to gather 278*333d2b36SAndroid Build Coastguard Worker// the complete visibility lists from flat lists and after the package info is gathered to ensure 279*333d2b36SAndroid Build Coastguard Worker// that default_visibility is available. 280*333d2b36SAndroid Build Coastguard Workerfunc RegisterVisibilityRuleGatherer(ctx RegisterMutatorsContext) { 281*333d2b36SAndroid Build Coastguard Worker ctx.BottomUp("visibilityRuleGatherer", visibilityRuleGatherer) 282*333d2b36SAndroid Build Coastguard Worker} 283*333d2b36SAndroid Build Coastguard Worker 284*333d2b36SAndroid Build Coastguard Worker// This must be registered after the deps have been resolved. 285*333d2b36SAndroid Build Coastguard Workerfunc RegisterVisibilityRuleEnforcer(ctx RegisterMutatorsContext) { 286*333d2b36SAndroid Build Coastguard Worker ctx.BottomUp("visibilityRuleEnforcer", visibilityRuleEnforcer) 287*333d2b36SAndroid Build Coastguard Worker} 288*333d2b36SAndroid Build Coastguard Worker 289*333d2b36SAndroid Build Coastguard Worker// Checks the per-module visibility rule lists before defaults expansion. 290*333d2b36SAndroid Build Coastguard Workerfunc visibilityRuleChecker(ctx BottomUpMutatorContext) { 291*333d2b36SAndroid Build Coastguard Worker visibilityProperties := ctx.Module().visibilityProperties() 292*333d2b36SAndroid Build Coastguard Worker for _, p := range visibilityProperties { 293*333d2b36SAndroid Build Coastguard Worker if visibility := p.getStrings(); visibility != nil { 294*333d2b36SAndroid Build Coastguard Worker checkRules(ctx, ctx.ModuleDir(), p.getName(), visibility) 295*333d2b36SAndroid Build Coastguard Worker } 296*333d2b36SAndroid Build Coastguard Worker } 297*333d2b36SAndroid Build Coastguard Worker} 298*333d2b36SAndroid Build Coastguard Worker 299*333d2b36SAndroid Build Coastguard Workerfunc checkRules(ctx BaseModuleContext, currentPkg, property string, visibility []string) { 300*333d2b36SAndroid Build Coastguard Worker ruleCount := len(visibility) 301*333d2b36SAndroid Build Coastguard Worker if ruleCount == 0 { 302*333d2b36SAndroid Build Coastguard Worker // This prohibits an empty list as its meaning is unclear, e.g. it could mean no visibility and 303*333d2b36SAndroid Build Coastguard Worker // it could mean public visibility. Requiring at least one rule makes the owner's intent 304*333d2b36SAndroid Build Coastguard Worker // clearer. 305*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, "must contain at least one visibility rule") 306*333d2b36SAndroid Build Coastguard Worker return 307*333d2b36SAndroid Build Coastguard Worker } 308*333d2b36SAndroid Build Coastguard Worker 309*333d2b36SAndroid Build Coastguard Worker for i, v := range visibility { 310*333d2b36SAndroid Build Coastguard Worker ok, pkg, name := splitRule(ctx, v, currentPkg, property) 311*333d2b36SAndroid Build Coastguard Worker if !ok { 312*333d2b36SAndroid Build Coastguard Worker continue 313*333d2b36SAndroid Build Coastguard Worker } 314*333d2b36SAndroid Build Coastguard Worker 315*333d2b36SAndroid Build Coastguard Worker if pkg == "visibility" { 316*333d2b36SAndroid Build Coastguard Worker switch name { 317*333d2b36SAndroid Build Coastguard Worker case "private", "public": 318*333d2b36SAndroid Build Coastguard Worker case "legacy_public": 319*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, "//visibility:legacy_public must not be used") 320*333d2b36SAndroid Build Coastguard Worker continue 321*333d2b36SAndroid Build Coastguard Worker case "override": 322*333d2b36SAndroid Build Coastguard Worker // This keyword does not create a rule so pretend it does not exist. 323*333d2b36SAndroid Build Coastguard Worker ruleCount -= 1 324*333d2b36SAndroid Build Coastguard Worker default: 325*333d2b36SAndroid Build Coastguard Worker if anyPartitionRegex.MatchString(name) { 326*333d2b36SAndroid Build Coastguard Worker // any_*_partition can be used with another visibility fields 327*333d2b36SAndroid Build Coastguard Worker continue 328*333d2b36SAndroid Build Coastguard Worker } 329*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, "unrecognized visibility rule %q", v) 330*333d2b36SAndroid Build Coastguard Worker continue 331*333d2b36SAndroid Build Coastguard Worker } 332*333d2b36SAndroid Build Coastguard Worker if name == "override" { 333*333d2b36SAndroid Build Coastguard Worker if i != 0 { 334*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, `"%v" may only be used at the start of the visibility rules`, v) 335*333d2b36SAndroid Build Coastguard Worker } 336*333d2b36SAndroid Build Coastguard Worker } else if ruleCount != 1 { 337*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, "cannot mix %q with any other visibility rules", v) 338*333d2b36SAndroid Build Coastguard Worker continue 339*333d2b36SAndroid Build Coastguard Worker } 340*333d2b36SAndroid Build Coastguard Worker } 341*333d2b36SAndroid Build Coastguard Worker 342*333d2b36SAndroid Build Coastguard Worker // If the current directory is not in the vendor tree then there are some additional 343*333d2b36SAndroid Build Coastguard Worker // restrictions on the rules. 344*333d2b36SAndroid Build Coastguard Worker if !isAncestor("vendor", currentPkg) { 345*333d2b36SAndroid Build Coastguard Worker if !isAllowedFromOutsideVendor(pkg, name) { 346*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, 347*333d2b36SAndroid Build Coastguard Worker "%q is not allowed. Packages outside //vendor cannot make themselves visible to specific"+ 348*333d2b36SAndroid Build Coastguard Worker " targets within //vendor, they can only use //vendor:__subpackages__.", v) 349*333d2b36SAndroid Build Coastguard Worker continue 350*333d2b36SAndroid Build Coastguard Worker } 351*333d2b36SAndroid Build Coastguard Worker } 352*333d2b36SAndroid Build Coastguard Worker } 353*333d2b36SAndroid Build Coastguard Worker} 354*333d2b36SAndroid Build Coastguard Worker 355*333d2b36SAndroid Build Coastguard Worker// Gathers the flattened visibility rules after defaults expansion, parses the visibility 356*333d2b36SAndroid Build Coastguard Worker// properties, stores them in a map by qualifiedModuleName for retrieval during enforcement. 357*333d2b36SAndroid Build Coastguard Worker// 358*333d2b36SAndroid Build Coastguard Worker// See ../README.md#Visibility for information on the format of the visibility rules. 359*333d2b36SAndroid Build Coastguard Workerfunc visibilityRuleGatherer(ctx BottomUpMutatorContext) { 360*333d2b36SAndroid Build Coastguard Worker m := ctx.Module() 361*333d2b36SAndroid Build Coastguard Worker 362*333d2b36SAndroid Build Coastguard Worker qualifiedModuleId := m.qualifiedModuleId(ctx) 363*333d2b36SAndroid Build Coastguard Worker currentPkg := qualifiedModuleId.pkg 364*333d2b36SAndroid Build Coastguard Worker 365*333d2b36SAndroid Build Coastguard Worker // Parse the visibility rules that control access to the module and store them by id 366*333d2b36SAndroid Build Coastguard Worker // for use when enforcing the rules. 367*333d2b36SAndroid Build Coastguard Worker var rule compositeRule 368*333d2b36SAndroid Build Coastguard Worker primaryProperty := m.base().primaryVisibilityProperty 369*333d2b36SAndroid Build Coastguard Worker if primaryProperty != nil { 370*333d2b36SAndroid Build Coastguard Worker if visibility := primaryProperty.getStrings(); visibility != nil { 371*333d2b36SAndroid Build Coastguard Worker rule = parseRules(ctx, currentPkg, primaryProperty.getName(), visibility) 372*333d2b36SAndroid Build Coastguard Worker } 373*333d2b36SAndroid Build Coastguard Worker } 374*333d2b36SAndroid Build Coastguard Worker ipr := implicitPartitionRules(ctx) 375*333d2b36SAndroid Build Coastguard Worker if rule != nil || ipr != nil { 376*333d2b36SAndroid Build Coastguard Worker moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, visibilityRulesForModule{ 377*333d2b36SAndroid Build Coastguard Worker rule: rule, 378*333d2b36SAndroid Build Coastguard Worker implicitPartitionRules: ipr, 379*333d2b36SAndroid Build Coastguard Worker }) 380*333d2b36SAndroid Build Coastguard Worker } 381*333d2b36SAndroid Build Coastguard Worker} 382*333d2b36SAndroid Build Coastguard Worker 383*333d2b36SAndroid Build Coastguard Workerfunc parseRules(ctx BaseModuleContext, currentPkg, property string, visibility []string) compositeRule { 384*333d2b36SAndroid Build Coastguard Worker rules := make(compositeRule, 0, len(visibility)) 385*333d2b36SAndroid Build Coastguard Worker hasPrivateRule := false 386*333d2b36SAndroid Build Coastguard Worker hasPublicRule := false 387*333d2b36SAndroid Build Coastguard Worker hasNonPrivateRule := false 388*333d2b36SAndroid Build Coastguard Worker for _, v := range visibility { 389*333d2b36SAndroid Build Coastguard Worker ok, pkg, name := splitRule(ctx, v, currentPkg, property) 390*333d2b36SAndroid Build Coastguard Worker if !ok { 391*333d2b36SAndroid Build Coastguard Worker continue 392*333d2b36SAndroid Build Coastguard Worker } 393*333d2b36SAndroid Build Coastguard Worker 394*333d2b36SAndroid Build Coastguard Worker var r visibilityRule 395*333d2b36SAndroid Build Coastguard Worker isPrivateRule := false 396*333d2b36SAndroid Build Coastguard Worker if pkg == "visibility" { 397*333d2b36SAndroid Build Coastguard Worker switch name { 398*333d2b36SAndroid Build Coastguard Worker case "private": 399*333d2b36SAndroid Build Coastguard Worker r = privateRule{} 400*333d2b36SAndroid Build Coastguard Worker isPrivateRule = true 401*333d2b36SAndroid Build Coastguard Worker case "public": 402*333d2b36SAndroid Build Coastguard Worker r = publicRule{} 403*333d2b36SAndroid Build Coastguard Worker hasPublicRule = true 404*333d2b36SAndroid Build Coastguard Worker case "override": 405*333d2b36SAndroid Build Coastguard Worker // Discard all preceding rules and any state based on them. 406*333d2b36SAndroid Build Coastguard Worker rules = nil 407*333d2b36SAndroid Build Coastguard Worker hasPrivateRule = false 408*333d2b36SAndroid Build Coastguard Worker hasPublicRule = false 409*333d2b36SAndroid Build Coastguard Worker hasNonPrivateRule = false 410*333d2b36SAndroid Build Coastguard Worker // This does not actually create a rule so continue onto the next rule. 411*333d2b36SAndroid Build Coastguard Worker continue 412*333d2b36SAndroid Build Coastguard Worker default: 413*333d2b36SAndroid Build Coastguard Worker match := anyPartitionRegex.FindStringSubmatch(name) 414*333d2b36SAndroid Build Coastguard Worker if match != nil { 415*333d2b36SAndroid Build Coastguard Worker r = anyPartitionRule{ 416*333d2b36SAndroid Build Coastguard Worker partitionType: match[1], 417*333d2b36SAndroid Build Coastguard Worker } 418*333d2b36SAndroid Build Coastguard Worker } 419*333d2b36SAndroid Build Coastguard Worker } 420*333d2b36SAndroid Build Coastguard Worker } else { 421*333d2b36SAndroid Build Coastguard Worker switch name { 422*333d2b36SAndroid Build Coastguard Worker case "__pkg__": 423*333d2b36SAndroid Build Coastguard Worker r = packageRule{pkg} 424*333d2b36SAndroid Build Coastguard Worker case "__subpackages__": 425*333d2b36SAndroid Build Coastguard Worker r = subpackagesRule{pkg} 426*333d2b36SAndroid Build Coastguard Worker default: 427*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, "invalid visibility pattern %q. Must match "+ 428*333d2b36SAndroid Build Coastguard Worker " //<package>:<scope>, //<package> or :<scope> "+ 429*333d2b36SAndroid Build Coastguard Worker "where <scope> is one of \"__pkg__\", \"__subpackages__\"", 430*333d2b36SAndroid Build Coastguard Worker v) 431*333d2b36SAndroid Build Coastguard Worker } 432*333d2b36SAndroid Build Coastguard Worker } 433*333d2b36SAndroid Build Coastguard Worker 434*333d2b36SAndroid Build Coastguard Worker if isPrivateRule { 435*333d2b36SAndroid Build Coastguard Worker hasPrivateRule = true 436*333d2b36SAndroid Build Coastguard Worker } else { 437*333d2b36SAndroid Build Coastguard Worker hasNonPrivateRule = true 438*333d2b36SAndroid Build Coastguard Worker } 439*333d2b36SAndroid Build Coastguard Worker 440*333d2b36SAndroid Build Coastguard Worker rules = append(rules, r) 441*333d2b36SAndroid Build Coastguard Worker } 442*333d2b36SAndroid Build Coastguard Worker 443*333d2b36SAndroid Build Coastguard Worker if hasPrivateRule && hasNonPrivateRule { 444*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("visibility", 445*333d2b36SAndroid Build Coastguard Worker "cannot mix \"//visibility:private\" with any other visibility rules") 446*333d2b36SAndroid Build Coastguard Worker return compositeRule{privateRule{}} 447*333d2b36SAndroid Build Coastguard Worker } 448*333d2b36SAndroid Build Coastguard Worker 449*333d2b36SAndroid Build Coastguard Worker if hasPublicRule { 450*333d2b36SAndroid Build Coastguard Worker // Public overrides all other rules so just return it. 451*333d2b36SAndroid Build Coastguard Worker return compositeRule{publicRule{}} 452*333d2b36SAndroid Build Coastguard Worker } 453*333d2b36SAndroid Build Coastguard Worker 454*333d2b36SAndroid Build Coastguard Worker return rules 455*333d2b36SAndroid Build Coastguard Worker} 456*333d2b36SAndroid Build Coastguard Worker 457*333d2b36SAndroid Build Coastguard Workerfunc implicitPartitionRules(ctx BaseModuleContext) compositeRule { 458*333d2b36SAndroid Build Coastguard Worker var result compositeRule 459*333d2b36SAndroid Build Coastguard Worker if ctx.SocSpecific() { 460*333d2b36SAndroid Build Coastguard Worker result = append(result, anyPartitionRule{partitionType: "vendor"}) 461*333d2b36SAndroid Build Coastguard Worker } else if ctx.ProductSpecific() { 462*333d2b36SAndroid Build Coastguard Worker result = append(result, anyPartitionRule{partitionType: "product"}) 463*333d2b36SAndroid Build Coastguard Worker } else if ctx.Module().InstallInData() { 464*333d2b36SAndroid Build Coastguard Worker result = append(result, anyPartitionRule{partitionType: "data"}) 465*333d2b36SAndroid Build Coastguard Worker } else if ctx.SystemExtSpecific() { 466*333d2b36SAndroid Build Coastguard Worker result = append(result, anyPartitionRule{partitionType: "system_ext"}) 467*333d2b36SAndroid Build Coastguard Worker } else if ctx.DeviceSpecific() { 468*333d2b36SAndroid Build Coastguard Worker result = append(result, anyPartitionRule{partitionType: "odm"}) 469*333d2b36SAndroid Build Coastguard Worker } 470*333d2b36SAndroid Build Coastguard Worker return result 471*333d2b36SAndroid Build Coastguard Worker} 472*333d2b36SAndroid Build Coastguard Worker 473*333d2b36SAndroid Build Coastguard Workerfunc isAllowedFromOutsideVendor(pkg string, name string) bool { 474*333d2b36SAndroid Build Coastguard Worker if pkg == "vendor" { 475*333d2b36SAndroid Build Coastguard Worker return name == "__subpackages__" 476*333d2b36SAndroid Build Coastguard Worker } 477*333d2b36SAndroid Build Coastguard Worker 478*333d2b36SAndroid Build Coastguard Worker return !isAncestor("vendor", pkg) 479*333d2b36SAndroid Build Coastguard Worker} 480*333d2b36SAndroid Build Coastguard Worker 481*333d2b36SAndroid Build Coastguard Workerfunc splitRule(ctx BaseModuleContext, ruleExpression string, currentPkg, property string) (bool, string, string) { 482*333d2b36SAndroid Build Coastguard Worker // Make sure that the rule is of the correct format. 483*333d2b36SAndroid Build Coastguard Worker matches := visibilityRuleRegexp.FindStringSubmatch(ruleExpression) 484*333d2b36SAndroid Build Coastguard Worker if ruleExpression == "" || matches == nil { 485*333d2b36SAndroid Build Coastguard Worker // Visibility rule is invalid so ignore it. Keep going rather than aborting straight away to 486*333d2b36SAndroid Build Coastguard Worker // ensure all the rules on this module are checked. 487*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(property, 488*333d2b36SAndroid Build Coastguard Worker "invalid visibility pattern %q must match"+ 489*333d2b36SAndroid Build Coastguard Worker " //<package>:<scope>, //<package> or :<scope> "+ 490*333d2b36SAndroid Build Coastguard Worker "where <scope> is one of \"__pkg__\", \"__subpackages__\"", 491*333d2b36SAndroid Build Coastguard Worker ruleExpression) 492*333d2b36SAndroid Build Coastguard Worker return false, "", "" 493*333d2b36SAndroid Build Coastguard Worker } 494*333d2b36SAndroid Build Coastguard Worker 495*333d2b36SAndroid Build Coastguard Worker // Extract the package and name. 496*333d2b36SAndroid Build Coastguard Worker pkg := matches[1] 497*333d2b36SAndroid Build Coastguard Worker name := matches[2] 498*333d2b36SAndroid Build Coastguard Worker 499*333d2b36SAndroid Build Coastguard Worker // Normalize the short hands 500*333d2b36SAndroid Build Coastguard Worker if pkg == "" { 501*333d2b36SAndroid Build Coastguard Worker pkg = currentPkg 502*333d2b36SAndroid Build Coastguard Worker } 503*333d2b36SAndroid Build Coastguard Worker if name == "" { 504*333d2b36SAndroid Build Coastguard Worker name = "__pkg__" 505*333d2b36SAndroid Build Coastguard Worker } 506*333d2b36SAndroid Build Coastguard Worker 507*333d2b36SAndroid Build Coastguard Worker return true, pkg, name 508*333d2b36SAndroid Build Coastguard Worker} 509*333d2b36SAndroid Build Coastguard Worker 510*333d2b36SAndroid Build Coastguard Workerfunc visibilityRuleEnforcer(ctx BottomUpMutatorContext) { 511*333d2b36SAndroid Build Coastguard Worker qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.Module()) 512*333d2b36SAndroid Build Coastguard Worker 513*333d2b36SAndroid Build Coastguard Worker // Visit all the dependencies making sure that this module has access to them all. 514*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDeps(func(dep Module) { 515*333d2b36SAndroid Build Coastguard Worker // Ignore dependencies that have an ExcludeFromVisibilityEnforcementTag 516*333d2b36SAndroid Build Coastguard Worker tag := ctx.OtherModuleDependencyTag(dep) 517*333d2b36SAndroid Build Coastguard Worker if _, ok := tag.(ExcludeFromVisibilityEnforcementTag); ok { 518*333d2b36SAndroid Build Coastguard Worker return 519*333d2b36SAndroid Build Coastguard Worker } 520*333d2b36SAndroid Build Coastguard Worker 521*333d2b36SAndroid Build Coastguard Worker depName := ctx.OtherModuleName(dep) 522*333d2b36SAndroid Build Coastguard Worker depDir := ctx.OtherModuleDir(dep) 523*333d2b36SAndroid Build Coastguard Worker depQualified := qualifiedModuleName{depDir, depName} 524*333d2b36SAndroid Build Coastguard Worker 525*333d2b36SAndroid Build Coastguard Worker // Targets are always visible to other targets in their own package. 526*333d2b36SAndroid Build Coastguard Worker if depQualified.pkg == qualified.name.pkg { 527*333d2b36SAndroid Build Coastguard Worker return 528*333d2b36SAndroid Build Coastguard Worker } 529*333d2b36SAndroid Build Coastguard Worker 530*333d2b36SAndroid Build Coastguard Worker rule := effectiveVisibilityRules(ctx.Config(), depQualified) 531*333d2b36SAndroid Build Coastguard Worker if !rule.matches(qualified) { 532*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility", depQualified, "//"+ctx.ModuleDir()) 533*333d2b36SAndroid Build Coastguard Worker } 534*333d2b36SAndroid Build Coastguard Worker }) 535*333d2b36SAndroid Build Coastguard Worker} 536*333d2b36SAndroid Build Coastguard Worker 537*333d2b36SAndroid Build Coastguard Worker// Default visibility is public. 538*333d2b36SAndroid Build Coastguard Workervar defaultVisibility = compositeRule{publicRule{}} 539*333d2b36SAndroid Build Coastguard Worker 540*333d2b36SAndroid Build Coastguard Worker// Return the effective visibility rules. 541*333d2b36SAndroid Build Coastguard Worker// 542*333d2b36SAndroid Build Coastguard Worker// If no rules have been specified this will return the default visibility rule 543*333d2b36SAndroid Build Coastguard Worker// which is currently //visibility:public. 544*333d2b36SAndroid Build Coastguard Workerfunc effectiveVisibilityRules(config Config, qualified qualifiedModuleName) compositeRule { 545*333d2b36SAndroid Build Coastguard Worker moduleToVisibilityRule := moduleToVisibilityRuleMap(config) 546*333d2b36SAndroid Build Coastguard Worker value := visibilityRulesForModule{} 547*333d2b36SAndroid Build Coastguard Worker if valueRaw, ok := moduleToVisibilityRule.Load(qualified); ok { 548*333d2b36SAndroid Build Coastguard Worker value = valueRaw.(visibilityRulesForModule) 549*333d2b36SAndroid Build Coastguard Worker } 550*333d2b36SAndroid Build Coastguard Worker var rule compositeRule 551*333d2b36SAndroid Build Coastguard Worker if value.rule != nil { 552*333d2b36SAndroid Build Coastguard Worker rule = value.rule 553*333d2b36SAndroid Build Coastguard Worker } else { 554*333d2b36SAndroid Build Coastguard Worker rule = packageDefaultVisibility(moduleToVisibilityRule, qualified) 555*333d2b36SAndroid Build Coastguard Worker } 556*333d2b36SAndroid Build Coastguard Worker 557*333d2b36SAndroid Build Coastguard Worker // If no rule is specified then return the default visibility rule to avoid 558*333d2b36SAndroid Build Coastguard Worker // every caller having to treat nil as public. 559*333d2b36SAndroid Build Coastguard Worker if rule == nil { 560*333d2b36SAndroid Build Coastguard Worker rule = defaultVisibility 561*333d2b36SAndroid Build Coastguard Worker } 562*333d2b36SAndroid Build Coastguard Worker 563*333d2b36SAndroid Build Coastguard Worker // If a partition rule wasn't specified, add implicit partition visibility 564*333d2b36SAndroid Build Coastguard Worker // rules based on the partition properties like vendor: true. 565*333d2b36SAndroid Build Coastguard Worker foundPartitionRule := false 566*333d2b36SAndroid Build Coastguard Worker for _, r := range rule { 567*333d2b36SAndroid Build Coastguard Worker if _, ok := r.(anyPartitionRule); ok { 568*333d2b36SAndroid Build Coastguard Worker foundPartitionRule = true 569*333d2b36SAndroid Build Coastguard Worker break 570*333d2b36SAndroid Build Coastguard Worker } 571*333d2b36SAndroid Build Coastguard Worker } 572*333d2b36SAndroid Build Coastguard Worker if !foundPartitionRule { 573*333d2b36SAndroid Build Coastguard Worker rule = append(rule, value.implicitPartitionRules...) 574*333d2b36SAndroid Build Coastguard Worker } 575*333d2b36SAndroid Build Coastguard Worker 576*333d2b36SAndroid Build Coastguard Worker return rule 577*333d2b36SAndroid Build Coastguard Worker} 578*333d2b36SAndroid Build Coastguard Worker 579*333d2b36SAndroid Build Coastguard Workerfunc createQualifiedModuleName(moduleName, dir string) qualifiedModuleName { 580*333d2b36SAndroid Build Coastguard Worker qualified := qualifiedModuleName{dir, moduleName} 581*333d2b36SAndroid Build Coastguard Worker return qualified 582*333d2b36SAndroid Build Coastguard Worker} 583*333d2b36SAndroid Build Coastguard Worker 584*333d2b36SAndroid Build Coastguard Workerfunc packageDefaultVisibility(moduleToVisibilityRule *sync.Map, moduleId qualifiedModuleName) compositeRule { 585*333d2b36SAndroid Build Coastguard Worker packageQualifiedId := moduleId.getContainingPackageId() 586*333d2b36SAndroid Build Coastguard Worker for { 587*333d2b36SAndroid Build Coastguard Worker value, ok := moduleToVisibilityRule.Load(packageQualifiedId) 588*333d2b36SAndroid Build Coastguard Worker if ok { 589*333d2b36SAndroid Build Coastguard Worker return value.(visibilityRulesForModule).rule 590*333d2b36SAndroid Build Coastguard Worker } 591*333d2b36SAndroid Build Coastguard Worker 592*333d2b36SAndroid Build Coastguard Worker if packageQualifiedId.isRootPackage() { 593*333d2b36SAndroid Build Coastguard Worker return nil 594*333d2b36SAndroid Build Coastguard Worker } 595*333d2b36SAndroid Build Coastguard Worker 596*333d2b36SAndroid Build Coastguard Worker packageQualifiedId = packageQualifiedId.getContainingPackageId() 597*333d2b36SAndroid Build Coastguard Worker } 598*333d2b36SAndroid Build Coastguard Worker} 599*333d2b36SAndroid Build Coastguard Worker 600*333d2b36SAndroid Build Coastguard Workertype VisibilityRuleSet interface { 601*333d2b36SAndroid Build Coastguard Worker // Widen the visibility with some extra rules. 602*333d2b36SAndroid Build Coastguard Worker Widen(extra []string) error 603*333d2b36SAndroid Build Coastguard Worker 604*333d2b36SAndroid Build Coastguard Worker Strings() []string 605*333d2b36SAndroid Build Coastguard Worker} 606*333d2b36SAndroid Build Coastguard Worker 607*333d2b36SAndroid Build Coastguard Workertype visibilityRuleSet struct { 608*333d2b36SAndroid Build Coastguard Worker rules []string 609*333d2b36SAndroid Build Coastguard Worker} 610*333d2b36SAndroid Build Coastguard Worker 611*333d2b36SAndroid Build Coastguard Workervar _ VisibilityRuleSet = (*visibilityRuleSet)(nil) 612*333d2b36SAndroid Build Coastguard Worker 613*333d2b36SAndroid Build Coastguard Workerfunc (v *visibilityRuleSet) Widen(extra []string) error { 614*333d2b36SAndroid Build Coastguard Worker // Check the extra rules first just in case they are invalid. Otherwise, if 615*333d2b36SAndroid Build Coastguard Worker // the current visibility is public then the extra rules will just be ignored. 616*333d2b36SAndroid Build Coastguard Worker if len(extra) == 1 { 617*333d2b36SAndroid Build Coastguard Worker singularRule := extra[0] 618*333d2b36SAndroid Build Coastguard Worker switch singularRule { 619*333d2b36SAndroid Build Coastguard Worker case "//visibility:public": 620*333d2b36SAndroid Build Coastguard Worker // Public overrides everything so just discard any existing rules. 621*333d2b36SAndroid Build Coastguard Worker v.rules = extra 622*333d2b36SAndroid Build Coastguard Worker return nil 623*333d2b36SAndroid Build Coastguard Worker case "//visibility:private": 624*333d2b36SAndroid Build Coastguard Worker // Extending rule with private is an error. 625*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("%q does not widen the visibility", singularRule) 626*333d2b36SAndroid Build Coastguard Worker } 627*333d2b36SAndroid Build Coastguard Worker } 628*333d2b36SAndroid Build Coastguard Worker 629*333d2b36SAndroid Build Coastguard Worker if len(v.rules) == 1 { 630*333d2b36SAndroid Build Coastguard Worker switch v.rules[0] { 631*333d2b36SAndroid Build Coastguard Worker case "//visibility:public": 632*333d2b36SAndroid Build Coastguard Worker // No point in adding rules to something which is already public. 633*333d2b36SAndroid Build Coastguard Worker return nil 634*333d2b36SAndroid Build Coastguard Worker case "//visibility:private": 635*333d2b36SAndroid Build Coastguard Worker // Adding any rules to private means it is no longer private so the 636*333d2b36SAndroid Build Coastguard Worker // private can be discarded. 637*333d2b36SAndroid Build Coastguard Worker v.rules = nil 638*333d2b36SAndroid Build Coastguard Worker } 639*333d2b36SAndroid Build Coastguard Worker } 640*333d2b36SAndroid Build Coastguard Worker 641*333d2b36SAndroid Build Coastguard Worker v.rules = FirstUniqueStrings(append(v.rules, extra...)) 642*333d2b36SAndroid Build Coastguard Worker sort.Strings(v.rules) 643*333d2b36SAndroid Build Coastguard Worker return nil 644*333d2b36SAndroid Build Coastguard Worker} 645*333d2b36SAndroid Build Coastguard Worker 646*333d2b36SAndroid Build Coastguard Workerfunc (v *visibilityRuleSet) Strings() []string { 647*333d2b36SAndroid Build Coastguard Worker return v.rules 648*333d2b36SAndroid Build Coastguard Worker} 649*333d2b36SAndroid Build Coastguard Worker 650*333d2b36SAndroid Build Coastguard Worker// Get the effective visibility rules, i.e. the actual rules that affect the visibility of the 651*333d2b36SAndroid Build Coastguard Worker// property irrespective of where they are defined. 652*333d2b36SAndroid Build Coastguard Worker// 653*333d2b36SAndroid Build Coastguard Worker// Includes visibility rules specified by package default_visibility and/or on defaults. 654*333d2b36SAndroid Build Coastguard Worker// Short hand forms, e.g. //:__subpackages__ are replaced with their full form, e.g. 655*333d2b36SAndroid Build Coastguard Worker// //package/containing/rule:__subpackages__. 656*333d2b36SAndroid Build Coastguard Workerfunc EffectiveVisibilityRules(ctx BaseModuleContext, module Module) VisibilityRuleSet { 657*333d2b36SAndroid Build Coastguard Worker moduleName := ctx.OtherModuleName(module) 658*333d2b36SAndroid Build Coastguard Worker dir := ctx.OtherModuleDir(module) 659*333d2b36SAndroid Build Coastguard Worker qualified := qualifiedModuleName{dir, moduleName} 660*333d2b36SAndroid Build Coastguard Worker 661*333d2b36SAndroid Build Coastguard Worker rule := effectiveVisibilityRules(ctx.Config(), qualified) 662*333d2b36SAndroid Build Coastguard Worker 663*333d2b36SAndroid Build Coastguard Worker currentModule := createVisibilityModuleReference(moduleName, dir, module) 664*333d2b36SAndroid Build Coastguard Worker 665*333d2b36SAndroid Build Coastguard Worker // Modules are implicitly visible to other modules in the same package, 666*333d2b36SAndroid Build Coastguard Worker // without checking the visibility rules. Here we need to add that visibility 667*333d2b36SAndroid Build Coastguard Worker // explicitly. 668*333d2b36SAndroid Build Coastguard Worker if !rule.matches(currentModule) { 669*333d2b36SAndroid Build Coastguard Worker if len(rule) == 1 { 670*333d2b36SAndroid Build Coastguard Worker if _, ok := rule[0].(privateRule); ok { 671*333d2b36SAndroid Build Coastguard Worker // If the rule is //visibility:private we can't append another 672*333d2b36SAndroid Build Coastguard Worker // visibility to it. Semantically we need to convert it to a package 673*333d2b36SAndroid Build Coastguard Worker // visibility rule for the location where the result is used, but since 674*333d2b36SAndroid Build Coastguard Worker // modules are implicitly visible within the package we get the same 675*333d2b36SAndroid Build Coastguard Worker // result without any rule at all, so just make it an empty list to be 676*333d2b36SAndroid Build Coastguard Worker // appended below. 677*333d2b36SAndroid Build Coastguard Worker rule = nil 678*333d2b36SAndroid Build Coastguard Worker } 679*333d2b36SAndroid Build Coastguard Worker } 680*333d2b36SAndroid Build Coastguard Worker rule = append(rule, packageRule{dir}) 681*333d2b36SAndroid Build Coastguard Worker } 682*333d2b36SAndroid Build Coastguard Worker 683*333d2b36SAndroid Build Coastguard Worker return &visibilityRuleSet{rule.Strings()} 684*333d2b36SAndroid Build Coastguard Worker} 685*333d2b36SAndroid Build Coastguard Worker 686*333d2b36SAndroid Build Coastguard Worker// Clear the default visibility properties so they can be replaced. 687*333d2b36SAndroid Build Coastguard Workerfunc clearVisibilityProperties(module Module) { 688*333d2b36SAndroid Build Coastguard Worker module.base().visibilityPropertyInfo = nil 689*333d2b36SAndroid Build Coastguard Worker} 690*333d2b36SAndroid Build Coastguard Worker 691*333d2b36SAndroid Build Coastguard Worker// Add a property that contains visibility rules so that they are checked for 692*333d2b36SAndroid Build Coastguard Worker// correctness. 693*333d2b36SAndroid Build Coastguard Workerfunc AddVisibilityProperty(module Module, name string, stringsProperty *[]string) { 694*333d2b36SAndroid Build Coastguard Worker addVisibilityProperty(module, name, stringsProperty) 695*333d2b36SAndroid Build Coastguard Worker} 696*333d2b36SAndroid Build Coastguard Worker 697*333d2b36SAndroid Build Coastguard Workerfunc addVisibilityProperty(module Module, name string, stringsProperty *[]string) visibilityProperty { 698*333d2b36SAndroid Build Coastguard Worker base := module.base() 699*333d2b36SAndroid Build Coastguard Worker property := newVisibilityProperty(name, stringsProperty) 700*333d2b36SAndroid Build Coastguard Worker base.visibilityPropertyInfo = append(base.visibilityPropertyInfo, property) 701*333d2b36SAndroid Build Coastguard Worker return property 702*333d2b36SAndroid Build Coastguard Worker} 703*333d2b36SAndroid Build Coastguard Worker 704*333d2b36SAndroid Build Coastguard Worker// Set the primary visibility property. 705*333d2b36SAndroid Build Coastguard Worker// 706*333d2b36SAndroid Build Coastguard Worker// Also adds the property to the list of properties to be validated. 707*333d2b36SAndroid Build Coastguard Workerfunc setPrimaryVisibilityProperty(module Module, name string, stringsProperty *[]string) { 708*333d2b36SAndroid Build Coastguard Worker module.base().primaryVisibilityProperty = addVisibilityProperty(module, name, stringsProperty) 709*333d2b36SAndroid Build Coastguard Worker} 710