blob: 8d99d56f499127a70db2174d599d81c9db924d27 [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
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900181// Tests whether a module named moduleName is directly depended on by any APEX.
182func DirectlyInAnyApex(moduleName string) bool {
183 apexNamesMapMutex.Lock()
184 defer apexNamesMapMutex.Unlock()
185 if apexNames, ok := apexNamesMap()[moduleName]; ok {
186 for an := range apexNames {
187 if apexNames[an] {
Jiyong Park25fc6a92018-11-18 18:02:45 +0900188 return true
189 }
190 }
191 }
192 return false
193}
194
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900195// Tests whether a module named module is depended on (including both
196// direct and indirect dependencies) by any APEX.
197func InAnyApex(moduleName string) bool {
198 apexNamesMapMutex.Lock()
199 defer apexNamesMapMutex.Unlock()
200 apexNames, ok := apexNamesMap()[moduleName]
201 return ok && len(apexNames) > 0
202}
203
204func GetApexesForModule(moduleName string) []string {
205 ret := []string{}
206 apexNamesMapMutex.Lock()
207 defer apexNamesMapMutex.Unlock()
208 if apexNames, ok := apexNamesMap()[moduleName]; ok {
209 for an := range apexNames {
210 ret = append(ret, an)
211 }
212 }
213 return ret
Jiyong Parkde866cb2018-12-07 23:08:36 +0900214}
215
Jiyong Park9d452992018-10-03 00:38:19 +0900216func InitApexModule(m ApexModule) {
217 base := m.apexModuleBase()
218 base.canHaveApexVariants = true
219
220 m.AddProperties(&base.ApexProperties)
221}