blob: 077c4a464eea9e12450ee7b52760bba11fd8599c [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
104 // its checking and parsing phases.
105 module.primaryVisibilityProperty =
106 newVisibilityProperty("default_visibility", &module.properties.Default_visibility)
107 module.visibilityPropertyInfo = []visibilityProperty{module.primaryVisibilityProperty}
108
Paul Duffine2453c72019-05-31 14:00:04 +0100109 return module
110}
111
112// Registers the function that renames the packages.
Paul Duffin593b3c92019-12-05 14:31:48 +0000113func RegisterPackageRenamer(ctx RegisterMutatorsContext) {
Paul Duffine2453c72019-05-31 14:00:04 +0100114 ctx.BottomUp("packageRenamer", packageRenamer).Parallel()
115 ctx.BottomUp("packageErrorReporter", packageErrorReporter).Parallel()
116}
117
118// Renames the package to match the package directory.
119//
120// This also creates a PackageInfo object for each package and uses that to detect and remember
121// duplicates for later error reporting.
122func packageRenamer(ctx BottomUpMutatorContext) {
123 m, ok := ctx.Module().(*packageModule)
124 if !ok {
125 return
126 }
127
128 packageName := "//" + ctx.ModuleDir()
129
130 pi := newPackageInfo(ctx, packageName, m)
131 if pi.module != m {
132 // Remember that the package was duplicated but do not rename as that will cause an error to
133 // be logged with the generated name. Similarly, reporting the error here will use the generated
134 // name as renames are only processed after this phase.
135 pi.duplicated = true
136 } else {
137 // This is the first package module in this package so rename it to match the package name.
138 m.setName(packageName)
139 ctx.Rename(packageName)
140
141 // Store a package info reference in the module.
142 m.packageInfo = pi
143 }
144}
145
146// Logs any deferred errors.
147func packageErrorReporter(ctx BottomUpMutatorContext) {
148 m, ok := ctx.Module().(*packageModule)
149 if !ok {
150 return
151 }
152
153 packageDir := ctx.ModuleDir()
154 packageName := "//" + packageDir
155
156 // Get the PackageInfo for the package. Should have been populated in the packageRenamer phase.
157 pi := findPackageInfo(ctx, packageName)
158 if pi == nil {
159 ctx.ModuleErrorf("internal error, expected package info to be present for package '%s'",
160 packageName)
161 return
162 }
163
164 if pi.module != m {
165 // The package module has been duplicated but this is not the module that has been renamed so
166 // ignore it. An error will be logged for the renamed module which will ensure that the error
167 // message uses the correct name.
168 return
169 }
170
171 // Check to see whether there are duplicate package modules in the package.
172 if pi.duplicated {
173 ctx.ModuleErrorf("package {...} specified multiple times")
174 return
175 }
176}
177
178type defaultPackageInfoKey string
179
180func newPackageInfo(
181 ctx BaseModuleContext, packageName string, module *packageModule) *packageInfo {
182 key := NewCustomOnceKey(defaultPackageInfoKey(packageName))
183
184 return ctx.Config().Once(key, func() interface{} {
185 return &packageInfo{module: module}
186 }).(*packageInfo)
187}
188
189// Get the PackageInfo for the package name (starts with //, no trailing /), is nil if no package
190// module type was specified.
191func findPackageInfo(ctx BaseModuleContext, packageName string) *packageInfo {
192 key := NewCustomOnceKey(defaultPackageInfoKey(packageName))
193
194 pi := ctx.Config().Once(key, func() interface{} {
195 return nil
196 })
197
198 if pi == nil {
199 return nil
200 } else {
201 return pi.(*packageInfo)
202 }
203}