blob: a93baf6d4980413e68e2bfef119e46a101edbf24 [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 {
Logan Chien3aeedc92018-12-26 15:32:21 +0800125 variations := []string{""} // Original variation for platform
126 variations = append(variations, m.apexVariations...)
127
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900128 modules := mctx.CreateVariations(variations...)
129 for i, m := range modules {
130 if i == 0 {
Logan Chien3aeedc92018-12-26 15:32:21 +0800131 continue
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900132 }
133 m.(ApexModule).setApexName(variations[i])
134 }
135 return modules
136 }
137 return nil
138}
139
140var apexData OncePer
141var apexNamesMapMutex sync.Mutex
142
143// This structure maintains the global mapping in between modules and APEXes.
144// Examples:
Jiyong Park25fc6a92018-11-18 18:02:45 +0900145//
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900146// apexNamesMap()["foo"]["bar"] == true: module foo is directly depended on by APEX bar
147// apexNamesMap()["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
148// apexNamesMap()["foo"]["bar"] doesn't exist: foo is not built for APEX bar
149func apexNamesMap() map[string]map[string]bool {
150 return apexData.Once("apexNames", func() interface{} {
Jiyong Park25fc6a92018-11-18 18:02:45 +0900151 return make(map[string]map[string]bool)
152 }).(map[string]map[string]bool)
153}
154
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900155// Update the map to mark that a module named moduleName is directly or indirectly
156// depended on by an APEX named apexName. Directly depending means that a module
157// is explicitly listed in the build definition of the APEX via properties like
158// native_shared_libs, java_libs, etc.
159func UpdateApexDependency(apexName string, moduleName string, directDep bool) {
160 apexNamesMapMutex.Lock()
161 defer apexNamesMapMutex.Unlock()
162 apexNames, ok := apexNamesMap()[moduleName]
Jiyong Park25fc6a92018-11-18 18:02:45 +0900163 if !ok {
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900164 apexNames = make(map[string]bool)
165 apexNamesMap()[moduleName] = apexNames
Jiyong Park25fc6a92018-11-18 18:02:45 +0900166 }
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900167 apexNames[apexName] = apexNames[apexName] || directDep
Jiyong Park25fc6a92018-11-18 18:02:45 +0900168}
169
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900170// Tests whether a module named moduleName is directly depended on by an APEX
171// named apexName.
172func DirectlyInApex(apexName string, moduleName string) bool {
173 apexNamesMapMutex.Lock()
174 defer apexNamesMapMutex.Unlock()
175 if apexNames, ok := apexNamesMap()[moduleName]; ok {
176 return apexNames[apexName]
Jiyong Park25fc6a92018-11-18 18:02:45 +0900177 }
178 return false
179}
180
Nicolas Geoffrayc22c1bf2019-01-15 19:53:23 +0000181type hostContext interface {
182 Host() bool
183}
184
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900185// Tests whether a module named moduleName is directly depended on by any APEX.
Nicolas Geoffrayc22c1bf2019-01-15 19:53:23 +0000186func DirectlyInAnyApex(ctx hostContext, moduleName string) bool {
187 if ctx.Host() {
188 // Host has no APEX.
189 return false
190 }
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900191 apexNamesMapMutex.Lock()
192 defer apexNamesMapMutex.Unlock()
193 if apexNames, ok := apexNamesMap()[moduleName]; ok {
194 for an := range apexNames {
195 if apexNames[an] {
Jiyong Park25fc6a92018-11-18 18:02:45 +0900196 return true
197 }
198 }
199 }
200 return false
201}
202
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900203// Tests whether a module named module is depended on (including both
204// direct and indirect dependencies) by any APEX.
205func InAnyApex(moduleName string) bool {
206 apexNamesMapMutex.Lock()
207 defer apexNamesMapMutex.Unlock()
208 apexNames, ok := apexNamesMap()[moduleName]
209 return ok && len(apexNames) > 0
210}
211
212func GetApexesForModule(moduleName string) []string {
213 ret := []string{}
214 apexNamesMapMutex.Lock()
215 defer apexNamesMapMutex.Unlock()
216 if apexNames, ok := apexNamesMap()[moduleName]; ok {
217 for an := range apexNames {
218 ret = append(ret, an)
219 }
220 }
221 return ret
Jiyong Parkde866cb2018-12-07 23:08:36 +0900222}
223
Jiyong Park9d452992018-10-03 00:38:19 +0900224func InitApexModule(m ApexModule) {
225 base := m.apexModuleBase()
226 base.canHaveApexVariants = true
227
228 m.AddProperties(&base.ApexProperties)
229}