| Paul Duffin | e2453c7 | 2019-05-31 14:00:04 +0100 | [diff] [blame] | 1 | // Copyright 2019 Google Inc. All rights reserved. | 
|  | 2 | // | 
|  | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 | // you may not use this file except in compliance with the License. | 
|  | 5 | // You may obtain a copy of the License at | 
|  | 6 | // | 
|  | 7 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 | // | 
|  | 9 | // Unless required by applicable law or agreed to in writing, software | 
|  | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 | // See the License for the specific language governing permissions and | 
|  | 13 | // limitations under the License. | 
|  | 14 |  | 
|  | 15 | package android | 
|  | 16 |  | 
|  | 17 | import ( | 
|  | 18 | "fmt" | 
|  | 19 | "sync/atomic" | 
|  | 20 |  | 
|  | 21 | "github.com/google/blueprint" | 
|  | 22 | ) | 
|  | 23 |  | 
|  | 24 | func init() { | 
|  | 25 | RegisterModuleType("package", PackageFactory) | 
|  | 26 | } | 
|  | 27 |  | 
|  | 28 | // The information maintained about each package. | 
|  | 29 | type packageInfo struct { | 
|  | 30 | // The module from which this information was populated. If `duplicated` = true then this is the | 
|  | 31 | // module that has been renamed and must be used to report errors. | 
|  | 32 | module *packageModule | 
|  | 33 |  | 
|  | 34 | // If true this indicates that there are two package statements in the same package which is not | 
|  | 35 | // allowed and will cause the build to fail. This flag is set by packageRenamer and checked in | 
|  | 36 | // packageErrorReporter | 
|  | 37 | duplicated bool | 
|  | 38 | } | 
|  | 39 |  | 
|  | 40 | type packageProperties struct { | 
|  | 41 | Name string `blueprint:"mutated"` | 
|  | 42 |  | 
|  | 43 | // Specifies the default visibility for all modules defined in this package. | 
|  | 44 | Default_visibility []string | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | type packageModule struct { | 
|  | 48 | ModuleBase | 
|  | 49 |  | 
|  | 50 | properties  packageProperties | 
|  | 51 | packageInfo *packageInfo | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) { | 
|  | 55 | // Nothing to do. | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) { | 
|  | 59 | // Nothing to do. | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | func (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName { | 
|  | 63 | // Override to create a package id. | 
|  | 64 | return newPackageId(ctx.ModuleDir()) | 
|  | 65 | } | 
|  | 66 |  | 
| Paul Duffin | e2453c7 | 2019-05-31 14:00:04 +0100 | [diff] [blame] | 67 | func (p *packageModule) Name() string { | 
|  | 68 | return p.properties.Name | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | func (p *packageModule) setName(name string) { | 
|  | 72 | p.properties.Name = name | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | // Counter to ensure package modules are created with a unique name within whatever namespace they | 
|  | 76 | // belong. | 
|  | 77 | var packageCount uint32 = 0 | 
|  | 78 |  | 
|  | 79 | func PackageFactory() Module { | 
|  | 80 | module := &packageModule{} | 
|  | 81 |  | 
|  | 82 | // Get a unique if for the package. Has to be done atomically as the creation of the modules are | 
|  | 83 | // done in parallel. | 
|  | 84 | id := atomic.AddUint32(&packageCount, 1) | 
|  | 85 | name := fmt.Sprintf("soong_package_%d", id) | 
|  | 86 |  | 
|  | 87 | module.properties.Name = name | 
|  | 88 |  | 
|  | 89 | module.AddProperties(&module.properties) | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 90 |  | 
|  | 91 | // The default_visibility property needs to be checked and parsed by the visibility module during | 
|  | 92 | // its checking and parsing phases. | 
|  | 93 | module.primaryVisibilityProperty = | 
|  | 94 | newVisibilityProperty("default_visibility", &module.properties.Default_visibility) | 
|  | 95 | module.visibilityPropertyInfo = []visibilityProperty{module.primaryVisibilityProperty} | 
|  | 96 |  | 
| Paul Duffin | e2453c7 | 2019-05-31 14:00:04 +0100 | [diff] [blame] | 97 | return module | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | // Registers the function that renames the packages. | 
|  | 101 | func registerPackageRenamer(ctx RegisterMutatorsContext) { | 
|  | 102 | ctx.BottomUp("packageRenamer", packageRenamer).Parallel() | 
|  | 103 | ctx.BottomUp("packageErrorReporter", packageErrorReporter).Parallel() | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | // Renames the package to match the package directory. | 
|  | 107 | // | 
|  | 108 | // This also creates a PackageInfo object for each package and uses that to detect and remember | 
|  | 109 | // duplicates for later error reporting. | 
|  | 110 | func packageRenamer(ctx BottomUpMutatorContext) { | 
|  | 111 | m, ok := ctx.Module().(*packageModule) | 
|  | 112 | if !ok { | 
|  | 113 | return | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | packageName := "//" + ctx.ModuleDir() | 
|  | 117 |  | 
|  | 118 | pi := newPackageInfo(ctx, packageName, m) | 
|  | 119 | if pi.module != m { | 
|  | 120 | // Remember that the package was duplicated but do not rename as that will cause an error to | 
|  | 121 | // be logged with the generated name. Similarly, reporting the error here will use the generated | 
|  | 122 | // name as renames are only processed after this phase. | 
|  | 123 | pi.duplicated = true | 
|  | 124 | } else { | 
|  | 125 | // This is the first package module in this package so rename it to match the package name. | 
|  | 126 | m.setName(packageName) | 
|  | 127 | ctx.Rename(packageName) | 
|  | 128 |  | 
|  | 129 | // Store a package info reference in the module. | 
|  | 130 | m.packageInfo = pi | 
|  | 131 | } | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | // Logs any deferred errors. | 
|  | 135 | func packageErrorReporter(ctx BottomUpMutatorContext) { | 
|  | 136 | m, ok := ctx.Module().(*packageModule) | 
|  | 137 | if !ok { | 
|  | 138 | return | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | packageDir := ctx.ModuleDir() | 
|  | 142 | packageName := "//" + packageDir | 
|  | 143 |  | 
|  | 144 | // Get the PackageInfo for the package. Should have been populated in the packageRenamer phase. | 
|  | 145 | pi := findPackageInfo(ctx, packageName) | 
|  | 146 | if pi == nil { | 
|  | 147 | ctx.ModuleErrorf("internal error, expected package info to be present for package '%s'", | 
|  | 148 | packageName) | 
|  | 149 | return | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | if pi.module != m { | 
|  | 153 | // The package module has been duplicated but this is not the module that has been renamed so | 
|  | 154 | // ignore it. An error will be logged for the renamed module which will ensure that the error | 
|  | 155 | // message uses the correct name. | 
|  | 156 | return | 
|  | 157 | } | 
|  | 158 |  | 
|  | 159 | // Check to see whether there are duplicate package modules in the package. | 
|  | 160 | if pi.duplicated { | 
|  | 161 | ctx.ModuleErrorf("package {...} specified multiple times") | 
|  | 162 | return | 
|  | 163 | } | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | type defaultPackageInfoKey string | 
|  | 167 |  | 
|  | 168 | func newPackageInfo( | 
|  | 169 | ctx BaseModuleContext, packageName string, module *packageModule) *packageInfo { | 
|  | 170 | key := NewCustomOnceKey(defaultPackageInfoKey(packageName)) | 
|  | 171 |  | 
|  | 172 | return ctx.Config().Once(key, func() interface{} { | 
|  | 173 | return &packageInfo{module: module} | 
|  | 174 | }).(*packageInfo) | 
|  | 175 | } | 
|  | 176 |  | 
|  | 177 | // Get the PackageInfo for the package name (starts with //, no trailing /), is nil if no package | 
|  | 178 | // module type was specified. | 
|  | 179 | func findPackageInfo(ctx BaseModuleContext, packageName string) *packageInfo { | 
|  | 180 | key := NewCustomOnceKey(defaultPackageInfoKey(packageName)) | 
|  | 181 |  | 
|  | 182 | pi := ctx.Config().Once(key, func() interface{} { | 
|  | 183 | return nil | 
|  | 184 | }) | 
|  | 185 |  | 
|  | 186 | if pi == nil { | 
|  | 187 | return nil | 
|  | 188 | } else { | 
|  | 189 | return pi.(*packageInfo) | 
|  | 190 | } | 
|  | 191 | } |