blob: 3a191cf60853848288c00a1111457953473f5f2c [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 Park25fc6a92018-11-18 18:02:45 +090017import "sync"
18
Jiyong Park9d452992018-10-03 00:38:19 +090019// ApexModule is the interface that a module type is expected to implement if
20// the module has to be built differently depending on whether the module
21// is destined for an apex or not (installed to one of the regular partitions).
22//
23// Native shared libraries are one such module type; when it is built for an
24// APEX, it should depend only on stable interfaces such as NDK, stable AIDL,
25// or C APIs from other APEXs.
26//
27// A module implementing this interface will be mutated into multiple
28// variations by the apex mutator if it is directly or indirectly included
29// in one or more APEXs. Specifically, if a module is included in apex.foo and
30// apex.bar then three apex variants are created: platform, apex.foo and
31// apex.bar. The platform variant is for the regular partitions
32// (e.g., /system or /vendor, etc.) while the other two are for the APEXs,
33// respectively.
34type ApexModule interface {
35 Module
36 apexModuleBase() *ApexModuleBase
37
38 // Marks that this module should be built for the APEX of the specified name
39 BuildForApex(apexName string)
40
41 // Tests whether this module will be built for the platform or not (= APEXs)
42 IsForPlatform() bool
43
44 // Returns the name of APEX that this module will be built for. Empty string
45 // is returned when 'IsForPlatform() == true'. Note that a module can be
46 // included to multiple APEXs, in which case, the module is mutated into
47 // multiple modules each of which for an APEX. This method returns the
48 // name of the APEX that a variant module is for.
49 ApexName() string
50
51 // Tests if this module can have APEX variants. APEX variants are
52 // created only for the modules that returns true here. This is useful
53 // for not creating APEX variants for shared libraries such as NDK stubs.
54 CanHaveApexVariants() bool
55
56 // Tests if this module can be installed to APEX as a file. For example,
57 // this would return true for shared libs while return false for static
58 // libs.
59 IsInstallableToApex() bool
60}
61
62type ApexProperties struct {
63 ApexName string `blueprint:"mutated"`
64}
65
66// Provides default implementation for the ApexModule interface. APEX-aware
67// modules are expected to include this struct and call InitApexModule().
68type ApexModuleBase struct {
69 ApexProperties ApexProperties
70
71 canHaveApexVariants bool
72}
73
74func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
75 return m
76}
77
78func (m *ApexModuleBase) BuildForApex(apexName string) {
79 m.ApexProperties.ApexName = apexName
80}
81
82func (m *ApexModuleBase) IsForPlatform() bool {
83 return m.ApexProperties.ApexName == ""
84}
85
86func (m *ApexModuleBase) ApexName() string {
87 return m.ApexProperties.ApexName
88}
89
90func (m *ApexModuleBase) CanHaveApexVariants() bool {
91 return m.canHaveApexVariants
92}
93
94func (m *ApexModuleBase) IsInstallableToApex() bool {
95 // should be overriden if needed
96 return false
97}
98
Jiyong Park25fc6a92018-11-18 18:02:45 +090099// This structure maps a module name to the set of APEX bundle names that the module
100// should be built for. Examples:
101//
102// ...["foo"]["bar"] == true: module foo is directly depended on by APEX bar
103// ...["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
104// ...["foo"]["bar"] doesn't exist: foo is not built for APEX bar
105// ...["foo"] doesn't exist: foo is not built for any APEX
106func apexBundleNamesMap(config Config) map[string]map[string]bool {
107 return config.Once("apexBundleNames", func() interface{} {
108 return make(map[string]map[string]bool)
109 }).(map[string]map[string]bool)
110}
111
112var bundleNamesMapMutex sync.Mutex
113
114// Mark that a module named moduleName should be built for an apex named bundleName
115// directDep should be set to true if the module is a direct dependency of the apex.
116func BuildModuleForApexBundle(ctx BaseModuleContext, moduleName string, bundleName string, directDep bool) {
117 bundleNamesMapMutex.Lock()
118 defer bundleNamesMapMutex.Unlock()
119 bundleNames, ok := apexBundleNamesMap(ctx.Config())[moduleName]
120 if !ok {
121 bundleNames = make(map[string]bool)
122 apexBundleNamesMap(ctx.Config())[moduleName] = bundleNames
123 }
124 bundleNames[bundleName] = bundleNames[bundleName] || directDep
125}
126
127// Returns the list of apex bundle names that the module named moduleName
128// should be built for.
129func GetApexBundlesForModule(ctx BaseModuleContext, moduleName string) map[string]bool {
130 bundleNamesMapMutex.Lock()
131 defer bundleNamesMapMutex.Unlock()
132 return apexBundleNamesMap(ctx.Config())[moduleName]
133}
134
135// Tests if moduleName is directly depended on by bundleName (i.e. referenced in
136// native_shared_libs, etc.)
137func DirectlyInApex(config Config, bundleName string, moduleName string) bool {
138 bundleNamesMapMutex.Lock()
139 defer bundleNamesMapMutex.Unlock()
140 if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
141 return bundleNames[bundleName]
142 }
143 return false
144}
145
146// Tests if moduleName is directly depended on by any APEX. If this returns true,
147// that means the module is part of the platform.
148func DirectlyInAnyApex(config Config, moduleName string) bool {
149 bundleNamesMapMutex.Lock()
150 defer bundleNamesMapMutex.Unlock()
151 if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
152 for bn := range bundleNames {
153 if bundleNames[bn] {
154 return true
155 }
156 }
157 }
158 return false
159}
160
Jiyong Park9d452992018-10-03 00:38:19 +0900161func InitApexModule(m ApexModule) {
162 base := m.apexModuleBase()
163 base.canHaveApexVariants = true
164
165 m.AddProperties(&base.ApexProperties)
166}