blob: bb5f4e79ee1ca9522c0d966d22a63a7e77000d0c [file] [log] [blame]
Paul Duffine2453c72019-05-31 14:00:04 +01001// 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
15package android
16
17import (
18 "fmt"
19 "sync/atomic"
20
21 "github.com/google/blueprint"
22)
23
24func init() {
Paul Duffinc1327422020-01-14 12:15:29 +000025 RegisterPackageBuildComponents(InitRegistrationContext)
26}
27
28// Register the package module type and supporting mutators.
29//
30// This must be called in the correct order (relative to other methods that also
31// register mutators) to match the order of mutator registration in mutator.go.
32// Failing to do so will result in an unrealistic test environment.
33func RegisterPackageBuildComponents(ctx RegistrationContext) {
34 ctx.RegisterModuleType("package", PackageFactory)
35
36 // Register mutators that are hard coded in to mutator.go.
37 ctx.HardCodedPreArchMutators(RegisterPackageRenamer)
Paul Duffine2453c72019-05-31 14:00:04 +010038}
39
40// The information maintained about each package.
41type packageInfo struct {
42 // The module from which this information was populated. If `duplicated` = true then this is the
43 // module that has been renamed and must be used to report errors.
44 module *packageModule
45
46 // If true this indicates that there are two package statements in the same package which is not
47 // allowed and will cause the build to fail. This flag is set by packageRenamer and checked in
48 // packageErrorReporter
49 duplicated bool
50}
51
52type packageProperties struct {
53 Name string `blueprint:"mutated"`
54
55 // Specifies the default visibility for all modules defined in this package.
56 Default_visibility []string
57}
58
59type packageModule struct {
60 ModuleBase
61
62 properties packageProperties
63 packageInfo *packageInfo
64}
65
66func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) {
67 // Nothing to do.
68}
69
70func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
71 // Nothing to do.
72}
73
74func (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName {
75 // Override to create a package id.
76 return newPackageId(ctx.ModuleDir())
77}
78
Paul Duffine2453c72019-05-31 14:00:04 +010079func (p *packageModule) Name() string {
80 return p.properties.Name
81}
82
83func (p *packageModule) setName(name string) {
84 p.properties.Name = name
85}
86
87// Counter to ensure package modules are created with a unique name within whatever namespace they
88// belong.
89var packageCount uint32 = 0
90
91func PackageFactory() Module {
92 module := &packageModule{}
93
94 // Get a unique if for the package. Has to be done atomically as the creation of the modules are
95 // done in parallel.
96 id := atomic.AddUint32(&packageCount, 1)
97 name := fmt.Sprintf("soong_package_%d", id)
98
99 module.properties.Name = name
100
101 module.AddProperties(&module.properties)
Paul Duffin63c6e182019-07-24 14:24:38 +0100102
103 // The default_visibility property needs to be checked and parsed by the visibility module during
Paul Duffin5ec73ec2020-05-01 17:52:01 +0100104 // its checking and parsing phases so make it the primary visibility property.
105 setPrimaryVisibilityProperty(module, "default_visibility", &module.properties.Default_visibility)
Paul Duffin63c6e182019-07-24 14:24:38 +0100106
Paul Duffine2453c72019-05-31 14:00:04 +0100107 return module
108}
109
110// Registers the function that renames the packages.
Paul Duffin593b3c92019-12-05 14:31:48 +0000111func RegisterPackageRenamer(ctx RegisterMutatorsContext) {
Paul Duffine2453c72019-05-31 14:00:04 +0100112 ctx.BottomUp("packageRenamer", packageRenamer).Parallel()
113 ctx.BottomUp("packageErrorReporter", packageErrorReporter).Parallel()
114}
115
116// Renames the package to match the package directory.
117//
118// This also creates a PackageInfo object for each package and uses that to detect and remember
119// duplicates for later error reporting.
120func packageRenamer(ctx BottomUpMutatorContext) {
121 m, ok := ctx.Module().(*packageModule)
122 if !ok {
123 return
124 }
125
126 packageName := "//" + ctx.ModuleDir()
127
128 pi := newPackageInfo(ctx, packageName, m)
129 if pi.module != m {
130 // Remember that the package was duplicated but do not rename as that will cause an error to
131 // be logged with the generated name. Similarly, reporting the error here will use the generated
132 // name as renames are only processed after this phase.
133 pi.duplicated = true
134 } else {
135 // This is the first package module in this package so rename it to match the package name.
136 m.setName(packageName)
137 ctx.Rename(packageName)
138
139 // Store a package info reference in the module.
140 m.packageInfo = pi
141 }
142}
143
144// Logs any deferred errors.
145func packageErrorReporter(ctx BottomUpMutatorContext) {
146 m, ok := ctx.Module().(*packageModule)
147 if !ok {
148 return
149 }
150
151 packageDir := ctx.ModuleDir()
152 packageName := "//" + packageDir
153
154 // Get the PackageInfo for the package. Should have been populated in the packageRenamer phase.
155 pi := findPackageInfo(ctx, packageName)
156 if pi == nil {
157 ctx.ModuleErrorf("internal error, expected package info to be present for package '%s'",
158 packageName)
159 return
160 }
161
162 if pi.module != m {
163 // The package module has been duplicated but this is not the module that has been renamed so
164 // ignore it. An error will be logged for the renamed module which will ensure that the error
165 // message uses the correct name.
166 return
167 }
168
169 // Check to see whether there are duplicate package modules in the package.
170 if pi.duplicated {
171 ctx.ModuleErrorf("package {...} specified multiple times")
172 return
173 }
174}
175
176type defaultPackageInfoKey string
177
178func newPackageInfo(
179 ctx BaseModuleContext, packageName string, module *packageModule) *packageInfo {
180 key := NewCustomOnceKey(defaultPackageInfoKey(packageName))
181
182 return ctx.Config().Once(key, func() interface{} {
183 return &packageInfo{module: module}
184 }).(*packageInfo)
185}
186
187// Get the PackageInfo for the package name (starts with //, no trailing /), is nil if no package
188// module type was specified.
189func findPackageInfo(ctx BaseModuleContext, packageName string) *packageInfo {
190 key := NewCustomOnceKey(defaultPackageInfoKey(packageName))
191
192 pi := ctx.Config().Once(key, func() interface{} {
193 return nil
194 })
195
196 if pi == nil {
197 return nil
198 } else {
199 return pi.(*packageInfo)
200 }
201}