blob: d089c285d6df1ea3662358e907e4af833a3fd1f6 [file] [log] [blame]
Jiyong Park09d77522019-11-18 11:16:27 +09001// Copyright (C) 2019 The Android Open Source Project
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 apex
16
17import (
18 "fmt"
19 "strings"
20
21 "android/soong/android"
22
23 "github.com/google/blueprint/proptools"
24)
25
26type Prebuilt struct {
27 android.ModuleBase
28 prebuilt android.Prebuilt
29
30 properties PrebuiltProperties
31
32 inputApex android.Path
33 installDir android.InstallPath
34 installFilename string
35 outputApex android.WritablePath
Jooyung Han002ab682020-01-08 01:57:58 +090036
37 // list of commands to create symlinks for backward compatibility.
38 // these commands will be attached as LOCAL_POST_INSTALL_CMD
39 compatSymlinks []string
Jiyong Park09d77522019-11-18 11:16:27 +090040}
41
42type PrebuiltProperties struct {
43 // the path to the prebuilt .apex file to import.
44 Source string `blueprint:"mutated"`
45 ForceDisable bool `blueprint:"mutated"`
46
47 Src *string
48 Arch struct {
49 Arm struct {
50 Src *string
51 }
52 Arm64 struct {
53 Src *string
54 }
55 X86 struct {
56 Src *string
57 }
58 X86_64 struct {
59 Src *string
60 }
61 }
62
63 Installable *bool
64 // Optional name for the installed apex. If unspecified, name of the
65 // module is used as the file name
66 Filename *string
67
68 // Names of modules to be overridden. Listed modules can only be other binaries
69 // (in Make or Soong).
70 // This does not completely prevent installation of the overridden binaries, but if both
71 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
72 // from PRODUCT_PACKAGES.
73 Overrides []string
74}
75
76func (p *Prebuilt) installable() bool {
77 return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
78}
79
80func (p *Prebuilt) isForceDisabled() bool {
81 return p.properties.ForceDisable
82}
83
84func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) {
85 switch tag {
86 case "":
87 return android.Paths{p.outputApex}, nil
88 default:
89 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
90 }
91}
92
93func (p *Prebuilt) InstallFilename() string {
94 return proptools.StringDefault(p.properties.Filename, p.BaseModuleName()+imageApexSuffix)
95}
96
97func (p *Prebuilt) Prebuilt() *android.Prebuilt {
98 return &p.prebuilt
99}
100
101func (p *Prebuilt) Name() string {
102 return p.prebuilt.Name(p.ModuleBase.Name())
103}
104
105// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
106func PrebuiltFactory() android.Module {
107 module := &Prebuilt{}
108 module.AddProperties(&module.properties)
109 android.InitSingleSourcePrebuiltModule(module, &module.properties, "Source")
110 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
111 return module
112}
113
114func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
115 // If the device is configured to use flattened APEX, force disable the prebuilt because
116 // the prebuilt is a non-flattened one.
117 forceDisable := ctx.Config().FlattenApex()
118
119 // Force disable the prebuilts when we are doing unbundled build. We do unbundled build
120 // to build the prebuilts themselves.
121 forceDisable = forceDisable || ctx.Config().UnbundledBuild()
122
123 // Force disable the prebuilts when coverage is enabled.
124 forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled()
125 forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
126
127 // b/137216042 don't use prebuilts when address sanitizer is on
128 forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
129 android.InList("hwaddress", ctx.Config().SanitizeDevice())
130
131 if forceDisable && p.prebuilt.SourceExists() {
132 p.properties.ForceDisable = true
133 return
134 }
135
136 // This is called before prebuilt_select and prebuilt_postdeps mutators
137 // The mutators requires that src to be set correctly for each arch so that
138 // arch variants are disabled when src is not provided for the arch.
139 if len(ctx.MultiTargets()) != 1 {
140 ctx.ModuleErrorf("compile_multilib shouldn't be \"both\" for prebuilt_apex")
141 return
142 }
143 var src string
144 switch ctx.MultiTargets()[0].Arch.ArchType {
145 case android.Arm:
146 src = String(p.properties.Arch.Arm.Src)
147 case android.Arm64:
148 src = String(p.properties.Arch.Arm64.Src)
149 case android.X86:
150 src = String(p.properties.Arch.X86.Src)
151 case android.X86_64:
152 src = String(p.properties.Arch.X86_64.Src)
153 default:
154 ctx.ModuleErrorf("prebuilt_apex does not support %q", ctx.MultiTargets()[0].Arch.String())
155 return
156 }
157 if src == "" {
158 src = String(p.properties.Src)
159 }
160 p.properties.Source = src
161}
162
163func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
164 if p.properties.ForceDisable {
165 return
166 }
167
168 // TODO(jungjw): Check the key validity.
169 p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
170 p.installDir = android.PathForModuleInstall(ctx, "apex")
171 p.installFilename = p.InstallFilename()
172 if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
173 ctx.ModuleErrorf("filename should end in %s for prebuilt_apex", imageApexSuffix)
174 }
175 p.outputApex = android.PathForModuleOut(ctx, p.installFilename)
176 ctx.Build(pctx, android.BuildParams{
177 Rule: android.Cp,
178 Input: p.inputApex,
179 Output: p.outputApex,
180 })
181 if p.installable() {
182 ctx.InstallFile(p.installDir, p.installFilename, p.inputApex)
183 }
184
Jooyung Han002ab682020-01-08 01:57:58 +0900185 // in case that prebuilt_apex replaces source apex (using prefer: prop)
186 p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx)
187 // or that prebuilt_apex overrides other apexes (using overrides: prop)
188 for _, overridden := range p.properties.Overrides {
189 p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx)...)
190 }
Jiyong Park09d77522019-11-18 11:16:27 +0900191}
192
Jiyong Park0b0e1b92019-12-03 13:24:29 +0900193func (p *Prebuilt) AndroidMkEntries() []android.AndroidMkEntries {
194 return []android.AndroidMkEntries{android.AndroidMkEntries{
Jiyong Park09d77522019-11-18 11:16:27 +0900195 Class: "ETC",
196 OutputFile: android.OptionalPathForPath(p.inputApex),
197 Include: "$(BUILD_PREBUILT)",
198 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
199 func(entries *android.AndroidMkEntries) {
200 entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String())
201 entries.SetString("LOCAL_MODULE_STEM", p.installFilename)
202 entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
203 entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.properties.Overrides...)
Jooyung Han002ab682020-01-08 01:57:58 +0900204 if len(p.compatSymlinks) > 0 {
205 entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(p.compatSymlinks, " && "))
206 }
Jiyong Park09d77522019-11-18 11:16:27 +0900207 },
208 },
Jiyong Park0b0e1b92019-12-03 13:24:29 +0900209 }}
Jiyong Park09d77522019-11-18 11:16:27 +0900210}