blob: d1fb6f4ef260af1a199ba704a2dfcd5150ef91ab [file] [log] [blame]
Jiyong Park9d452992018-10-03 00:38:19 +09001// Copyright 2018 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
Jiyong Park0ddfcd12018-12-11 01:35:25 +090017import (
18 "sync"
19
20 "github.com/google/blueprint"
21)
Jiyong Park25fc6a92018-11-18 18:02:45 +090022
Jiyong Park9d452992018-10-03 00:38:19 +090023// ApexModule is the interface that a module type is expected to implement if
24// the module has to be built differently depending on whether the module
25// is destined for an apex or not (installed to one of the regular partitions).
26//
27// Native shared libraries are one such module type; when it is built for an
28// APEX, it should depend only on stable interfaces such as NDK, stable AIDL,
29// or C APIs from other APEXs.
30//
31// A module implementing this interface will be mutated into multiple
Jiyong Park0ddfcd12018-12-11 01:35:25 +090032// variations by apex.apexMutator if it is directly or indirectly included
Jiyong Park9d452992018-10-03 00:38:19 +090033// in one or more APEXs. Specifically, if a module is included in apex.foo and
34// apex.bar then three apex variants are created: platform, apex.foo and
35// apex.bar. The platform variant is for the regular partitions
36// (e.g., /system or /vendor, etc.) while the other two are for the APEXs,
37// respectively.
38type ApexModule interface {
39 Module
40 apexModuleBase() *ApexModuleBase
41
Jiyong Park0ddfcd12018-12-11 01:35:25 +090042 // Marks that this module should be built for the APEX of the specified name.
43 // Call this before apex.apexMutator is run.
Jiyong Park9d452992018-10-03 00:38:19 +090044 BuildForApex(apexName string)
45
Jiyong Park9d452992018-10-03 00:38:19 +090046 // Returns the name of APEX that this module will be built for. Empty string
47 // is returned when 'IsForPlatform() == true'. Note that a module can be
Jiyong Park0ddfcd12018-12-11 01:35:25 +090048 // included in multiple APEXes, in which case, the module is mutated into
Jiyong Park9d452992018-10-03 00:38:19 +090049 // multiple modules each of which for an APEX. This method returns the
50 // name of the APEX that a variant module is for.
Jiyong Park0ddfcd12018-12-11 01:35:25 +090051 // Call this after apex.apexMutator is run.
Jiyong Park9d452992018-10-03 00:38:19 +090052 ApexName() string
53
Jiyong Park0ddfcd12018-12-11 01:35:25 +090054 // Tests whether this module will be built for the platform or not.
55 // This is a shortcut for ApexName() == ""
56 IsForPlatform() bool
57
58 // Tests if this module could have APEX variants. APEX variants are
Jiyong Park9d452992018-10-03 00:38:19 +090059 // created only for the modules that returns true here. This is useful
Jiyong Park0ddfcd12018-12-11 01:35:25 +090060 // for not creating APEX variants for certain types of shared libraries
61 // such as NDK stubs.
Jiyong Park9d452992018-10-03 00:38:19 +090062 CanHaveApexVariants() bool
63
64 // Tests if this module can be installed to APEX as a file. For example,
65 // this would return true for shared libs while return false for static
66 // libs.
67 IsInstallableToApex() bool
Jiyong Park0ddfcd12018-12-11 01:35:25 +090068
69 // Mutate this module into one or more variants each of which is built
70 // for an APEX marked via BuildForApex().
71 CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module
72
73 // Sets the name of the apex variant of this module. Called inside
74 // CreateApexVariations.
75 setApexName(apexName string)
Jiyong Park9d452992018-10-03 00:38:19 +090076}
77
78type ApexProperties struct {
Jiyong Park0ddfcd12018-12-11 01:35:25 +090079 // Name of the apex variant that this module is mutated into
Jiyong Park9d452992018-10-03 00:38:19 +090080 ApexName string `blueprint:"mutated"`
81}
82
83// Provides default implementation for the ApexModule interface. APEX-aware
84// modules are expected to include this struct and call InitApexModule().
85type ApexModuleBase struct {
86 ApexProperties ApexProperties
87
88 canHaveApexVariants bool
Jiyong Park0ddfcd12018-12-11 01:35:25 +090089 apexVariations []string
Jiyong Park9d452992018-10-03 00:38:19 +090090}
91
92func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
93 return m
94}
95
96func (m *ApexModuleBase) BuildForApex(apexName string) {
Jiyong Park0ddfcd12018-12-11 01:35:25 +090097 if !InList(apexName, m.apexVariations) {
98 m.apexVariations = append(m.apexVariations, apexName)
99 }
100}
101
102func (m *ApexModuleBase) ApexName() string {
103 return m.ApexProperties.ApexName
Jiyong Park9d452992018-10-03 00:38:19 +0900104}
105
106func (m *ApexModuleBase) IsForPlatform() bool {
107 return m.ApexProperties.ApexName == ""
108}
109
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900110func (m *ApexModuleBase) setApexName(apexName string) {
111 m.ApexProperties.ApexName = apexName
Jiyong Park9d452992018-10-03 00:38:19 +0900112}
113
114func (m *ApexModuleBase) CanHaveApexVariants() bool {
115 return m.canHaveApexVariants
116}
117
118func (m *ApexModuleBase) IsInstallableToApex() bool {
119 // should be overriden if needed
120 return false
121}
122
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900123func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module {
124 if len(m.apexVariations) > 0 {
125 // The original module is mutated into "platform" variation.
126 variations := []string{"platform"}
127 for _, a := range m.apexVariations {
128 variations = append(variations, a)
129 }
130 modules := mctx.CreateVariations(variations...)
131 for i, m := range modules {
132 if i == 0 {
133 continue // platform
134 }
135 m.(ApexModule).setApexName(variations[i])
136 }
137 return modules
138 }
139 return nil
140}
141
142var apexData OncePer
143var apexNamesMapMutex sync.Mutex
144
145// This structure maintains the global mapping in between modules and APEXes.
146// Examples:
Jiyong Park25fc6a92018-11-18 18:02:45 +0900147//
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900148// apexNamesMap()["foo"]["bar"] == true: module foo is directly depended on by APEX bar
149// apexNamesMap()["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
150// apexNamesMap()["foo"]["bar"] doesn't exist: foo is not built for APEX bar
151func apexNamesMap() map[string]map[string]bool {
152 return apexData.Once("apexNames", func() interface{} {
Jiyong Park25fc6a92018-11-18 18:02:45 +0900153 return make(map[string]map[string]bool)
154 }).(map[string]map[string]bool)
155}
156
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900157// Update the map to mark that a module named moduleName is directly or indirectly
158// depended on by an APEX named apexName. Directly depending means that a module
159// is explicitly listed in the build definition of the APEX via properties like
160// native_shared_libs, java_libs, etc.
161func UpdateApexDependency(apexName string, moduleName string, directDep bool) {
162 apexNamesMapMutex.Lock()
163 defer apexNamesMapMutex.Unlock()
164 apexNames, ok := apexNamesMap()[moduleName]
Jiyong Park25fc6a92018-11-18 18:02:45 +0900165 if !ok {
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900166 apexNames = make(map[string]bool)
167 apexNamesMap()[moduleName] = apexNames
Jiyong Park25fc6a92018-11-18 18:02:45 +0900168 }
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900169 apexNames[apexName] = apexNames[apexName] || directDep
Jiyong Park25fc6a92018-11-18 18:02:45 +0900170}
171
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900172// Tests whether a module named moduleName is directly depended on by an APEX
173// named apexName.
174func DirectlyInApex(apexName string, moduleName string) bool {
175 apexNamesMapMutex.Lock()
176 defer apexNamesMapMutex.Unlock()
177 if apexNames, ok := apexNamesMap()[moduleName]; ok {
178 return apexNames[apexName]
Jiyong Park25fc6a92018-11-18 18:02:45 +0900179 }
180 return false
181}
182
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900183// Tests whether a module named moduleName is directly depended on by any APEX.
184func DirectlyInAnyApex(moduleName string) bool {
185 apexNamesMapMutex.Lock()
186 defer apexNamesMapMutex.Unlock()
187 if apexNames, ok := apexNamesMap()[moduleName]; ok {
188 for an := range apexNames {
189 if apexNames[an] {
Jiyong Park25fc6a92018-11-18 18:02:45 +0900190 return true
191 }
192 }
193 }
194 return false
195}
196
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900197// Tests whether a module named module is depended on (including both
198// direct and indirect dependencies) by any APEX.
199func InAnyApex(moduleName string) bool {
200 apexNamesMapMutex.Lock()
201 defer apexNamesMapMutex.Unlock()
202 apexNames, ok := apexNamesMap()[moduleName]
203 return ok && len(apexNames) > 0
204}
205
206func GetApexesForModule(moduleName string) []string {
207 ret := []string{}
208 apexNamesMapMutex.Lock()
209 defer apexNamesMapMutex.Unlock()
210 if apexNames, ok := apexNamesMap()[moduleName]; ok {
211 for an := range apexNames {
212 ret = append(ret, an)
213 }
214 }
215 return ret
Jiyong Parkde866cb2018-12-07 23:08:36 +0900216}
217
Jiyong Park9d452992018-10-03 00:38:19 +0900218func InitApexModule(m ApexModule) {
219 base := m.apexModuleBase()
220 base.canHaveApexVariants = true
221
222 m.AddProperties(&base.ApexProperties)
223}