blob: 0219b847deab3f3858ec69c56b7a4851a015a5cf [file] [log] [blame]
Inseob Kim8471cda2019-11-15 09:59:12 +09001// Copyright 2020 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.
14package cc
15
16import (
17 "encoding/json"
18 "path/filepath"
19 "sort"
20 "strings"
Inseob Kimeec88e12020-01-22 11:11:29 +090021 "sync"
Inseob Kim8471cda2019-11-15 09:59:12 +090022
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26)
27
Inseob Kimeec88e12020-01-22 11:11:29 +090028const (
29 vendorSnapshotHeaderSuffix = ".vendor_header."
30 vendorSnapshotSharedSuffix = ".vendor_shared."
31 vendorSnapshotStaticSuffix = ".vendor_static."
32 vendorSnapshotBinarySuffix = ".vendor_binary."
Inseob Kim1042d292020-06-01 23:23:05 +090033 vendorSnapshotObjectSuffix = ".vendor_object."
Inseob Kimeec88e12020-01-22 11:11:29 +090034)
35
36var (
37 vendorSnapshotsLock sync.Mutex
38 vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules")
39 vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs")
40 vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs")
41 vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs")
42 vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries")
Inseob Kim1042d292020-06-01 23:23:05 +090043 vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects")
Inseob Kimeec88e12020-01-22 11:11:29 +090044)
45
Inseob Kim5f64aec2020-02-18 17:27:19 +090046// vendor snapshot maps hold names of vendor snapshot modules per arch
Inseob Kimeec88e12020-01-22 11:11:29 +090047func vendorSuffixModules(config android.Config) map[string]bool {
48 return config.Once(vendorSuffixModulesKey, func() interface{} {
49 return make(map[string]bool)
50 }).(map[string]bool)
51}
52
53func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap {
54 return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} {
55 return newSnapshotMap()
56 }).(*snapshotMap)
57}
58
59func vendorSnapshotSharedLibs(config android.Config) *snapshotMap {
60 return config.Once(vendorSnapshotSharedLibsKey, func() interface{} {
61 return newSnapshotMap()
62 }).(*snapshotMap)
63}
64
65func vendorSnapshotStaticLibs(config android.Config) *snapshotMap {
66 return config.Once(vendorSnapshotStaticLibsKey, func() interface{} {
67 return newSnapshotMap()
68 }).(*snapshotMap)
69}
70
71func vendorSnapshotBinaries(config android.Config) *snapshotMap {
72 return config.Once(vendorSnapshotBinariesKey, func() interface{} {
73 return newSnapshotMap()
74 }).(*snapshotMap)
75}
76
Inseob Kim1042d292020-06-01 23:23:05 +090077func vendorSnapshotObjects(config android.Config) *snapshotMap {
78 return config.Once(vendorSnapshotObjectsKey, func() interface{} {
79 return newSnapshotMap()
80 }).(*snapshotMap)
81}
82
Inseob Kim2d34ad92020-07-30 21:04:09 +090083type vendorSnapshotBaseProperties struct {
Inseob Kimeec88e12020-01-22 11:11:29 +090084 // snapshot version.
85 Version string
86
87 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
88 Target_arch string
Inseob Kim2d34ad92020-07-30 21:04:09 +090089}
Inseob Kimeec88e12020-01-22 11:11:29 +090090
Inseob Kim2d34ad92020-07-30 21:04:09 +090091// vendorSnapshotModuleBase provides common basic functions for all snapshot modules.
92type vendorSnapshotModuleBase struct {
93 baseProperties vendorSnapshotBaseProperties
94 moduleSuffix string
95}
96
97func (p *vendorSnapshotModuleBase) Name(name string) string {
98 return name + p.NameSuffix()
99}
100
101func (p *vendorSnapshotModuleBase) NameSuffix() string {
102 versionSuffix := p.version()
103 if p.arch() != "" {
104 versionSuffix += "." + p.arch()
105 }
106
107 return p.moduleSuffix + versionSuffix
108}
109
110func (p *vendorSnapshotModuleBase) version() string {
111 return p.baseProperties.Version
112}
113
114func (p *vendorSnapshotModuleBase) arch() string {
115 return p.baseProperties.Target_arch
116}
117
118func (p *vendorSnapshotModuleBase) isSnapshotPrebuilt() bool {
119 return true
120}
121
122// Call this after creating a snapshot module with module suffix
123// such as vendorSnapshotSharedSuffix
124func (p *vendorSnapshotModuleBase) init(m *Module, suffix string) {
125 p.moduleSuffix = suffix
126 m.AddProperties(&p.baseProperties)
127 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
128 vendorSnapshotLoadHook(ctx, p)
129 })
130}
131
132func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *vendorSnapshotModuleBase) {
133 if p.version() != ctx.DeviceConfig().VndkVersion() {
134 ctx.Module().Disable()
135 return
136 }
137}
138
139type vendorSnapshotLibraryProperties struct {
Inseob Kimeec88e12020-01-22 11:11:29 +0900140 // Prebuilt file for each arch.
141 Src *string `android:"arch_variant"`
142
Inseob Kimc42f2f22020-07-29 20:32:10 +0900143 // list of directories that will be added to the include path (using -I).
144 Export_include_dirs []string `android:"arch_variant"`
145
146 // list of directories that will be added to the system path (using -isystem).
147 Export_system_include_dirs []string `android:"arch_variant"`
148
Inseob Kimeec88e12020-01-22 11:11:29 +0900149 // list of flags that will be used for any module that links against this module.
150 Export_flags []string `android:"arch_variant"`
151
Inseob Kimeec88e12020-01-22 11:11:29 +0900152 // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
153 Sanitize_ubsan_dep *bool `android:"arch_variant"`
154
155 // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
156 Sanitize_minimal_dep *bool `android:"arch_variant"`
157}
158
Inseob Kimc42f2f22020-07-29 20:32:10 +0900159type snapshotSanitizer interface {
160 isSanitizerEnabled(t sanitizerType) bool
161 setSanitizerVariation(t sanitizerType, enabled bool)
162}
163
Inseob Kimeec88e12020-01-22 11:11:29 +0900164type vendorSnapshotLibraryDecorator struct {
Inseob Kim2d34ad92020-07-30 21:04:09 +0900165 vendorSnapshotModuleBase
Inseob Kimeec88e12020-01-22 11:11:29 +0900166 *libraryDecorator
Inseob Kimc42f2f22020-07-29 20:32:10 +0900167 properties vendorSnapshotLibraryProperties
168 sanitizerProperties struct {
169 CfiEnabled bool `blueprint:"mutated"`
170
171 // Library flags for cfi variant.
172 Cfi vendorSnapshotLibraryProperties `android:"arch_variant"`
173 }
Inseob Kimeec88e12020-01-22 11:11:29 +0900174 androidMkVendorSuffix bool
175}
176
Inseob Kimeec88e12020-01-22 11:11:29 +0900177func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
178 p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
179 return p.libraryDecorator.linkerFlags(ctx, flags)
180}
181
182func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
183 arches := config.Arches()
184 if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
185 return false
186 }
187 if !p.header() && p.properties.Src == nil {
188 return false
189 }
190 return true
191}
192
193func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
194 flags Flags, deps PathDeps, objs Objects) android.Path {
195 m := ctx.Module().(*Module)
196 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
197
198 if p.header() {
199 return p.libraryDecorator.link(ctx, flags, deps, objs)
200 }
201
Inseob Kimc42f2f22020-07-29 20:32:10 +0900202 if p.sanitizerProperties.CfiEnabled {
203 p.properties = p.sanitizerProperties.Cfi
204 }
205
Inseob Kimeec88e12020-01-22 11:11:29 +0900206 if !p.matchesWithDevice(ctx.DeviceConfig()) {
207 return nil
208 }
209
Inseob Kimc42f2f22020-07-29 20:32:10 +0900210 p.libraryDecorator.reexportDirs(android.PathsForModuleSrc(ctx, p.properties.Export_include_dirs)...)
211 p.libraryDecorator.reexportSystemDirs(android.PathsForModuleSrc(ctx, p.properties.Export_system_include_dirs)...)
Inseob Kimeec88e12020-01-22 11:11:29 +0900212 p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
213
214 in := android.PathForModuleSrc(ctx, *p.properties.Src)
215 p.unstrippedOutputFile = in
216
217 if p.shared() {
218 libName := in.Base()
219 builderFlags := flagsToBuilderFlags(flags)
220
221 // Optimize out relinking against shared libraries whose interface hasn't changed by
222 // depending on a table of contents file instead of the library itself.
223 tocFile := android.PathForModuleOut(ctx, libName+".toc")
224 p.tocFile = android.OptionalPathForPath(tocFile)
225 TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
226 }
227
228 return in
229}
230
Inseob Kimeec88e12020-01-22 11:11:29 +0900231func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
232 if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
233 p.baseInstaller.install(ctx, file)
234 }
235}
236
Inseob Kim2d34ad92020-07-30 21:04:09 +0900237func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
238 return false
Inseob Kimeec88e12020-01-22 11:11:29 +0900239}
240
Inseob Kimc42f2f22020-07-29 20:32:10 +0900241func (p *vendorSnapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
242 switch t {
243 case cfi:
244 return p.sanitizerProperties.Cfi.Src != nil
245 default:
246 return false
247 }
248}
249
250func (p *vendorSnapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) {
251 if !enabled {
252 return
253 }
254 switch t {
255 case cfi:
256 p.sanitizerProperties.CfiEnabled = true
257 default:
258 return
259 }
260}
261
Inseob Kim2d34ad92020-07-30 21:04:09 +0900262func vendorSnapshotLibrary(suffix string) (*Module, *vendorSnapshotLibraryDecorator) {
Inseob Kimeec88e12020-01-22 11:11:29 +0900263 module, library := NewLibrary(android.DeviceSupported)
264
265 module.stl = nil
266 module.sanitize = nil
Thiébaud Weksteend4587452020-08-19 14:53:01 +0200267 library.disableStripping()
Inseob Kimeec88e12020-01-22 11:11:29 +0900268
269 prebuilt := &vendorSnapshotLibraryDecorator{
270 libraryDecorator: library,
271 }
272
273 prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
274 prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
275
276 // Prevent default system libs (libc, libm, and libdl) from being linked
277 if prebuilt.baseLinker.Properties.System_shared_libs == nil {
278 prebuilt.baseLinker.Properties.System_shared_libs = []string{}
279 }
280
281 module.compiler = nil
282 module.linker = prebuilt
283 module.installer = prebuilt
284
Inseob Kim2d34ad92020-07-30 21:04:09 +0900285 prebuilt.init(module, suffix)
Inseob Kimc42f2f22020-07-29 20:32:10 +0900286 module.AddProperties(
287 &prebuilt.properties,
288 &prebuilt.sanitizerProperties,
289 )
Inseob Kimeec88e12020-01-22 11:11:29 +0900290
291 return module, prebuilt
292}
293
294func VendorSnapshotSharedFactory() android.Module {
Inseob Kim2d34ad92020-07-30 21:04:09 +0900295 module, prebuilt := vendorSnapshotLibrary(vendorSnapshotSharedSuffix)
Inseob Kimeec88e12020-01-22 11:11:29 +0900296 prebuilt.libraryDecorator.BuildOnlyShared()
Inseob Kimeec88e12020-01-22 11:11:29 +0900297 return module.Init()
298}
299
300func VendorSnapshotStaticFactory() android.Module {
Inseob Kim2d34ad92020-07-30 21:04:09 +0900301 module, prebuilt := vendorSnapshotLibrary(vendorSnapshotStaticSuffix)
Inseob Kimeec88e12020-01-22 11:11:29 +0900302 prebuilt.libraryDecorator.BuildOnlyStatic()
Inseob Kimeec88e12020-01-22 11:11:29 +0900303 return module.Init()
304}
305
306func VendorSnapshotHeaderFactory() android.Module {
Inseob Kim2d34ad92020-07-30 21:04:09 +0900307 module, prebuilt := vendorSnapshotLibrary(vendorSnapshotHeaderSuffix)
Inseob Kimeec88e12020-01-22 11:11:29 +0900308 prebuilt.libraryDecorator.HeaderOnly()
Inseob Kimeec88e12020-01-22 11:11:29 +0900309 return module.Init()
310}
311
Inseob Kimc42f2f22020-07-29 20:32:10 +0900312var _ snapshotSanitizer = (*vendorSnapshotLibraryDecorator)(nil)
313
Inseob Kimeec88e12020-01-22 11:11:29 +0900314type vendorSnapshotBinaryProperties struct {
Inseob Kimeec88e12020-01-22 11:11:29 +0900315 // Prebuilt file for each arch.
316 Src *string `android:"arch_variant"`
317}
318
319type vendorSnapshotBinaryDecorator struct {
Inseob Kim2d34ad92020-07-30 21:04:09 +0900320 vendorSnapshotModuleBase
Inseob Kimeec88e12020-01-22 11:11:29 +0900321 *binaryDecorator
322 properties vendorSnapshotBinaryProperties
323 androidMkVendorSuffix bool
324}
325
Inseob Kimeec88e12020-01-22 11:11:29 +0900326func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
327 if config.DeviceArch() != p.arch() {
328 return false
329 }
330 if p.properties.Src == nil {
331 return false
332 }
333 return true
334}
335
336func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
337 flags Flags, deps PathDeps, objs Objects) android.Path {
338 if !p.matchesWithDevice(ctx.DeviceConfig()) {
339 return nil
340 }
341
342 in := android.PathForModuleSrc(ctx, *p.properties.Src)
Thiébaud Weksteend4587452020-08-19 14:53:01 +0200343 stripFlags := flagsToStripFlags(flags)
Inseob Kimeec88e12020-01-22 11:11:29 +0900344 p.unstrippedOutputFile = in
345 binName := in.Base()
Thiébaud Weksteend4587452020-08-19 14:53:01 +0200346 if p.stripper.NeedsStrip(ctx) {
Inseob Kimeec88e12020-01-22 11:11:29 +0900347 stripped := android.PathForModuleOut(ctx, "stripped", binName)
Thiébaud Weksteend4587452020-08-19 14:53:01 +0200348 p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags)
Inseob Kimeec88e12020-01-22 11:11:29 +0900349 in = stripped
350 }
351
352 m := ctx.Module().(*Module)
353 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
354
355 // use cpExecutable to make it executable
356 outputFile := android.PathForModuleOut(ctx, binName)
357 ctx.Build(pctx, android.BuildParams{
358 Rule: android.CpExecutable,
359 Description: "prebuilt",
360 Output: outputFile,
361 Input: in,
362 })
363
364 return outputFile
365}
366
Inseob Kim2d34ad92020-07-30 21:04:09 +0900367func (p *vendorSnapshotBinaryDecorator) nativeCoverage() bool {
368 return false
Inseob Kim1042d292020-06-01 23:23:05 +0900369}
370
Inseob Kimeec88e12020-01-22 11:11:29 +0900371func VendorSnapshotBinaryFactory() android.Module {
372 module, binary := NewBinary(android.DeviceSupported)
373 binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
374 binary.baseLinker.Properties.Nocrt = BoolPtr(true)
375
376 // Prevent default system libs (libc, libm, and libdl) from being linked
377 if binary.baseLinker.Properties.System_shared_libs == nil {
378 binary.baseLinker.Properties.System_shared_libs = []string{}
379 }
380
381 prebuilt := &vendorSnapshotBinaryDecorator{
382 binaryDecorator: binary,
383 }
384
385 module.compiler = nil
386 module.sanitize = nil
387 module.stl = nil
388 module.linker = prebuilt
389
Inseob Kim2d34ad92020-07-30 21:04:09 +0900390 prebuilt.init(module, vendorSnapshotBinarySuffix)
Inseob Kimeec88e12020-01-22 11:11:29 +0900391 module.AddProperties(&prebuilt.properties)
392 return module.Init()
393}
394
Inseob Kim1042d292020-06-01 23:23:05 +0900395type vendorSnapshotObjectProperties struct {
Inseob Kim1042d292020-06-01 23:23:05 +0900396 // Prebuilt file for each arch.
397 Src *string `android:"arch_variant"`
398}
399
400type vendorSnapshotObjectLinker struct {
Inseob Kim2d34ad92020-07-30 21:04:09 +0900401 vendorSnapshotModuleBase
Inseob Kim1042d292020-06-01 23:23:05 +0900402 objectLinker
403 properties vendorSnapshotObjectProperties
404 androidMkVendorSuffix bool
405}
406
Inseob Kim1042d292020-06-01 23:23:05 +0900407func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
408 if config.DeviceArch() != p.arch() {
409 return false
410 }
411 if p.properties.Src == nil {
412 return false
413 }
414 return true
415}
416
417func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext,
418 flags Flags, deps PathDeps, objs Objects) android.Path {
419 if !p.matchesWithDevice(ctx.DeviceConfig()) {
420 return nil
421 }
422
423 m := ctx.Module().(*Module)
424 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
425
426 return android.PathForModuleSrc(ctx, *p.properties.Src)
427}
428
429func (p *vendorSnapshotObjectLinker) nativeCoverage() bool {
430 return false
431}
432
Inseob Kim1042d292020-06-01 23:23:05 +0900433func VendorSnapshotObjectFactory() android.Module {
434 module := newObject()
435
436 prebuilt := &vendorSnapshotObjectLinker{
437 objectLinker: objectLinker{
438 baseLinker: NewBaseLinker(nil),
439 },
440 }
441 module.linker = prebuilt
442
Inseob Kim2d34ad92020-07-30 21:04:09 +0900443 prebuilt.init(module, vendorSnapshotObjectSuffix)
Inseob Kim1042d292020-06-01 23:23:05 +0900444 module.AddProperties(&prebuilt.properties)
445 return module.Init()
446}
447
Inseob Kim8471cda2019-11-15 09:59:12 +0900448func init() {
449 android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
Inseob Kimeec88e12020-01-22 11:11:29 +0900450 android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
451 android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
452 android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
453 android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
Inseob Kim1042d292020-06-01 23:23:05 +0900454 android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
Inseob Kim8471cda2019-11-15 09:59:12 +0900455}
456
457func VendorSnapshotSingleton() android.Singleton {
458 return &vendorSnapshotSingleton{}
459}
460
461type vendorSnapshotSingleton struct {
462 vendorSnapshotZipFile android.OptionalPath
463}
464
465var (
466 // Modules under following directories are ignored. They are OEM's and vendor's
Daniel Norman713387d2020-07-28 16:04:38 -0700467 // proprietary modules(device/, kernel/, vendor/, and hardware/).
Inseob Kim8471cda2019-11-15 09:59:12 +0900468 // TODO(b/65377115): Clean up these with more maintainable way
469 vendorProprietaryDirs = []string{
470 "device",
Daniel Norman713387d2020-07-28 16:04:38 -0700471 "kernel",
Inseob Kim8471cda2019-11-15 09:59:12 +0900472 "vendor",
473 "hardware",
474 }
475
476 // Modules under following directories are included as they are in AOSP,
Daniel Norman713387d2020-07-28 16:04:38 -0700477 // although hardware/ and kernel/ are normally for vendor's own.
Inseob Kim8471cda2019-11-15 09:59:12 +0900478 // TODO(b/65377115): Clean up these with more maintainable way
479 aospDirsUnderProprietary = []string{
Daniel Norman713387d2020-07-28 16:04:38 -0700480 "kernel/configs",
481 "kernel/prebuilts",
482 "kernel/tests",
Inseob Kim8471cda2019-11-15 09:59:12 +0900483 "hardware/interfaces",
484 "hardware/libhardware",
485 "hardware/libhardware_legacy",
486 "hardware/ril",
487 }
488)
489
490// Determine if a dir under source tree is an SoC-owned proprietary directory, such as
491// device/, vendor/, etc.
492func isVendorProprietaryPath(dir string) bool {
493 for _, p := range vendorProprietaryDirs {
494 if strings.HasPrefix(dir, p) {
495 // filter out AOSP defined directories, e.g. hardware/interfaces/
496 aosp := false
497 for _, p := range aospDirsUnderProprietary {
498 if strings.HasPrefix(dir, p) {
499 aosp = true
500 break
501 }
502 }
503 if !aosp {
504 return true
505 }
506 }
507 }
508 return false
509}
510
Bill Peckham945441c2020-08-31 16:07:58 -0700511func isVendorProprietaryModule(ctx android.BaseModuleContext) bool {
512
513 // Any module in a vendor proprietary path is a vendor proprietary
514 // module.
515
516 if isVendorProprietaryPath(ctx.ModuleDir()) {
517 return true
518 }
519
520 // However if the module is not in a vendor proprietary path, it may
521 // still be a vendor proprietary module. This happens for cc modules
522 // that are excluded from the vendor snapshot, and it means that the
523 // vendor has assumed control of the framework-provided module.
524
525 if c, ok := ctx.Module().(*Module); ok {
526 if c.ExcludeFromVendorSnapshot() {
527 return true
528 }
529 }
530
531 return false
532}
533
Inseob Kim8471cda2019-11-15 09:59:12 +0900534// Determine if a module is going to be included in vendor snapshot or not.
535//
536// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
537// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
538// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
539// image and newer system image altogether.
Bill Peckham945441c2020-08-31 16:07:58 -0700540func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool) bool {
Inseob Kim7f283f42020-06-01 21:53:49 +0900541 if !m.Enabled() || m.Properties.HideFromMake {
Inseob Kim8471cda2019-11-15 09:59:12 +0900542 return false
543 }
544 // skip proprietary modules, but include all VNDK (static)
Bill Peckham945441c2020-08-31 16:07:58 -0700545 if inVendorProprietaryPath && !m.IsVndk() {
546 return false
547 }
548 // If the module would be included based on its path, check to see if
549 // the module is marked to be excluded. If so, skip it.
550 if m.ExcludeFromVendorSnapshot() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900551 return false
552 }
553 if m.Target().Os.Class != android.Device {
554 return false
555 }
556 if m.Target().NativeBridge == android.NativeBridgeEnabled {
557 return false
558 }
559 // the module must be installed in /vendor
Inseob Kim7f283f42020-06-01 21:53:49 +0900560 if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900561 return false
562 }
Inseob Kim65ca36a2020-06-11 13:55:45 +0900563 // skip kernel_headers which always depend on vendor
564 if _, ok := m.linker.(*kernelHeadersDecorator); ok {
565 return false
566 }
Justin Yunf2664c62020-07-30 18:57:54 +0900567 // skip llndk_library and llndk_headers which are backward compatible
568 if _, ok := m.linker.(*llndkStubDecorator); ok {
569 return false
570 }
571 if _, ok := m.linker.(*llndkHeadersDecorator); ok {
572 return false
573 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900574
575 // Libraries
576 if l, ok := m.linker.(snapshotLibraryInterface); ok {
Inseob Kim7f283f42020-06-01 21:53:49 +0900577 // TODO(b/65377115): add full support for sanitizer
578 if m.sanitize != nil {
Inseob Kimc42f2f22020-07-29 20:32:10 +0900579 // scs and hwasan export both sanitized and unsanitized variants for static and header
Inseob Kim7f283f42020-06-01 21:53:49 +0900580 // Always use unsanitized variants of them.
Inseob Kimc42f2f22020-07-29 20:32:10 +0900581 for _, t := range []sanitizerType{scs, hwasan} {
Inseob Kim7f283f42020-06-01 21:53:49 +0900582 if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
583 return false
584 }
585 }
Inseob Kimc42f2f22020-07-29 20:32:10 +0900586 // cfi also exports both variants. But for static, we capture both.
587 if !l.static() && !l.shared() && m.sanitize.isSanitizerEnabled(cfi) {
588 return false
589 }
Inseob Kim7f283f42020-06-01 21:53:49 +0900590 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900591 if l.static() {
Inseob Kim7f283f42020-06-01 21:53:49 +0900592 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
Inseob Kim8471cda2019-11-15 09:59:12 +0900593 }
594 if l.shared() {
Bill Peckham7d3f0962020-06-29 16:49:15 -0700595 if !m.outputFile.Valid() {
596 return false
597 }
598 if !m.IsVndk() {
599 return true
600 }
601 return m.isVndkExt()
Inseob Kim8471cda2019-11-15 09:59:12 +0900602 }
603 return true
604 }
605
Inseob Kim1042d292020-06-01 23:23:05 +0900606 // Binaries and Objects
607 if m.binary() || m.object() {
Inseob Kim7f283f42020-06-01 21:53:49 +0900608 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
Inseob Kim8471cda2019-11-15 09:59:12 +0900609 }
Inseob Kim7f283f42020-06-01 21:53:49 +0900610
611 return false
Inseob Kim8471cda2019-11-15 09:59:12 +0900612}
613
614func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
615 // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
616 if ctx.DeviceConfig().VndkVersion() != "current" {
617 return
618 }
619
620 var snapshotOutputs android.Paths
621
622 /*
623 Vendor snapshot zipped artifacts directory structure:
624 {SNAPSHOT_ARCH}/
625 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
626 shared/
627 (.so shared libraries)
628 static/
629 (.a static libraries)
630 header/
631 (header only libraries)
632 binary/
633 (executable binaries)
Inseob Kim1042d292020-06-01 23:23:05 +0900634 object/
635 (.o object files)
Inseob Kim8471cda2019-11-15 09:59:12 +0900636 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
637 shared/
638 (.so shared libraries)
639 static/
640 (.a static libraries)
641 header/
642 (header only libraries)
643 binary/
644 (executable binaries)
Inseob Kim1042d292020-06-01 23:23:05 +0900645 object/
646 (.o object files)
Inseob Kim8471cda2019-11-15 09:59:12 +0900647 NOTICE_FILES/
648 (notice files, e.g. libbase.txt)
649 configs/
650 (config files, e.g. init.rc files, vintf_fragments.xml files, etc.)
651 include/
652 (header files of same directory structure with source tree)
653 */
654
655 snapshotDir := "vendor-snapshot"
656 snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
657
658 includeDir := filepath.Join(snapshotArchDir, "include")
659 configsDir := filepath.Join(snapshotArchDir, "configs")
660 noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
661
662 installedNotices := make(map[string]bool)
663 installedConfigs := make(map[string]bool)
664
665 var headers android.Paths
666
Inseob Kim8471cda2019-11-15 09:59:12 +0900667 installSnapshot := func(m *Module) android.Paths {
668 targetArch := "arch-" + m.Target().Arch.ArchType.String()
669 if m.Target().Arch.ArchVariant != "" {
670 targetArch += "-" + m.Target().Arch.ArchVariant
671 }
672
673 var ret android.Paths
674
675 prop := struct {
676 ModuleName string `json:",omitempty"`
677 RelativeInstallPath string `json:",omitempty"`
678
679 // library flags
680 ExportedDirs []string `json:",omitempty"`
681 ExportedSystemDirs []string `json:",omitempty"`
682 ExportedFlags []string `json:",omitempty"`
Inseob Kimc42f2f22020-07-29 20:32:10 +0900683 Sanitize string `json:",omitempty"`
Inseob Kim8471cda2019-11-15 09:59:12 +0900684 SanitizeMinimalDep bool `json:",omitempty"`
685 SanitizeUbsanDep bool `json:",omitempty"`
686
687 // binary flags
688 Symlinks []string `json:",omitempty"`
689
690 // dependencies
691 SharedLibs []string `json:",omitempty"`
692 RuntimeLibs []string `json:",omitempty"`
693 Required []string `json:",omitempty"`
694
695 // extra config files
696 InitRc []string `json:",omitempty"`
697 VintfFragments []string `json:",omitempty"`
698 }{}
699
700 // Common properties among snapshots.
701 prop.ModuleName = ctx.ModuleName(m)
Bill Peckham7d3f0962020-06-29 16:49:15 -0700702 if m.isVndkExt() {
703 // vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
704 if m.isVndkSp() {
705 prop.RelativeInstallPath = "vndk-sp"
706 } else {
707 prop.RelativeInstallPath = "vndk"
708 }
709 } else {
710 prop.RelativeInstallPath = m.RelativeInstallPath()
711 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900712 prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs
713 prop.Required = m.RequiredModuleNames()
714 for _, path := range m.InitRc() {
715 prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base()))
716 }
717 for _, path := range m.VintfFragments() {
718 prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base()))
719 }
720
721 // install config files. ignores any duplicates.
722 for _, path := range append(m.InitRc(), m.VintfFragments()...) {
723 out := filepath.Join(configsDir, path.Base())
724 if !installedConfigs[out] {
725 installedConfigs[out] = true
726 ret = append(ret, copyFile(ctx, path, out))
727 }
728 }
729
730 var propOut string
731
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900732 if l, ok := m.linker.(snapshotLibraryInterface); ok {
Inseob Kimc42f2f22020-07-29 20:32:10 +0900733
Inseob Kim8471cda2019-11-15 09:59:12 +0900734 // library flags
735 prop.ExportedFlags = l.exportedFlags()
736 for _, dir := range l.exportedDirs() {
737 prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String()))
738 }
739 for _, dir := range l.exportedSystemDirs() {
740 prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String()))
741 }
742 // shared libs dependencies aren't meaningful on static or header libs
743 if l.shared() {
744 prop.SharedLibs = m.Properties.SnapshotSharedLibs
745 }
746 if l.static() && m.sanitize != nil {
747 prop.SanitizeMinimalDep = m.sanitize.Properties.MinimalRuntimeDep || enableMinimalRuntime(m.sanitize)
748 prop.SanitizeUbsanDep = m.sanitize.Properties.UbsanRuntimeDep || enableUbsanRuntime(m.sanitize)
749 }
750
751 var libType string
752 if l.static() {
753 libType = "static"
754 } else if l.shared() {
755 libType = "shared"
756 } else {
757 libType = "header"
758 }
759
760 var stem string
761
762 // install .a or .so
763 if libType != "header" {
764 libPath := m.outputFile.Path()
765 stem = libPath.Base()
Inseob Kimc42f2f22020-07-29 20:32:10 +0900766 if l.static() && m.sanitize != nil && m.sanitize.isSanitizerEnabled(cfi) {
767 // both cfi and non-cfi variant for static libraries can exist.
768 // attach .cfi to distinguish between cfi and non-cfi.
769 // e.g. libbase.a -> libbase.cfi.a
770 ext := filepath.Ext(stem)
771 stem = strings.TrimSuffix(stem, ext) + ".cfi" + ext
772 prop.Sanitize = "cfi"
773 prop.ModuleName += ".cfi"
774 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900775 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
776 ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
777 } else {
778 stem = ctx.ModuleName(m)
779 }
780
781 propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json")
Inseob Kim7f283f42020-06-01 21:53:49 +0900782 } else if m.binary() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900783 // binary flags
784 prop.Symlinks = m.Symlinks()
785 prop.SharedLibs = m.Properties.SnapshotSharedLibs
786
787 // install bin
788 binPath := m.outputFile.Path()
789 snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
790 ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
791 propOut = snapshotBinOut + ".json"
Inseob Kim1042d292020-06-01 23:23:05 +0900792 } else if m.object() {
793 // object files aren't installed to the device, so their names can conflict.
794 // Use module name as stem.
795 objPath := m.outputFile.Path()
796 snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
797 ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
798 ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
799 propOut = snapshotObjOut + ".json"
Inseob Kim7f283f42020-06-01 21:53:49 +0900800 } else {
801 ctx.Errorf("unknown module %q in vendor snapshot", m.String())
802 return nil
Inseob Kim8471cda2019-11-15 09:59:12 +0900803 }
804
805 j, err := json.Marshal(prop)
806 if err != nil {
807 ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
808 return nil
809 }
810 ret = append(ret, writeStringToFile(ctx, string(j), propOut))
811
812 return ret
813 }
814
815 ctx.VisitAllModules(func(module android.Module) {
816 m, ok := module.(*Module)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900817 if !ok {
818 return
819 }
820
821 moduleDir := ctx.ModuleDir(module)
Bill Peckham945441c2020-08-31 16:07:58 -0700822 inVendorProprietaryPath := isVendorProprietaryPath(moduleDir)
823
824 if m.ExcludeFromVendorSnapshot() {
825 if inVendorProprietaryPath {
826 // Error: exclude_from_vendor_snapshot applies
827 // to framework-path modules only.
828 ctx.Errorf("module %q in vendor proprietary path %q may not use \"exclude_from_vendor_snapshot: true\"", m.String(), moduleDir)
829 return
830 }
831 if Bool(m.VendorProperties.Vendor_available) {
832 // Error: may not combine "vendor_available:
833 // true" with "exclude_from_vendor_snapshot:
834 // true".
835 ctx.Errorf("module %q may not use both \"vendor_available: true\" and \"exclude_from_vendor_snapshot: true\"", m.String())
836 return
837 }
838 }
839
840 if !isVendorSnapshotModule(m, inVendorProprietaryPath) {
Inseob Kim8471cda2019-11-15 09:59:12 +0900841 return
842 }
843
844 snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900845 if l, ok := m.linker.(snapshotLibraryInterface); ok {
846 headers = append(headers, l.snapshotHeaders()...)
Inseob Kim8471cda2019-11-15 09:59:12 +0900847 }
848
Bob Badoura75b0572020-02-18 20:21:55 -0800849 if len(m.NoticeFiles()) > 0 {
Inseob Kim8471cda2019-11-15 09:59:12 +0900850 noticeName := ctx.ModuleName(m) + ".txt"
851 noticeOut := filepath.Join(noticeDir, noticeName)
852 // skip already copied notice file
853 if !installedNotices[noticeOut] {
854 installedNotices[noticeOut] = true
Bob Badoura75b0572020-02-18 20:21:55 -0800855 snapshotOutputs = append(snapshotOutputs, combineNotices(
856 ctx, m.NoticeFiles(), noticeOut))
Inseob Kim8471cda2019-11-15 09:59:12 +0900857 }
858 }
859 })
860
861 // install all headers after removing duplicates
862 for _, header := range android.FirstUniquePaths(headers) {
863 snapshotOutputs = append(snapshotOutputs, copyFile(
864 ctx, header, filepath.Join(includeDir, header.String())))
865 }
866
867 // All artifacts are ready. Sort them to normalize ninja and then zip.
868 sort.Slice(snapshotOutputs, func(i, j int) bool {
869 return snapshotOutputs[i].String() < snapshotOutputs[j].String()
870 })
871
872 zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip")
873 zipRule := android.NewRuleBuilder()
874
875 // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
876 snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list")
877 zipRule.Command().
878 Text("tr").
879 FlagWithArg("-d ", "\\'").
880 FlagWithRspFileInputList("< ", snapshotOutputs).
881 FlagWithOutput("> ", snapshotOutputList)
882
883 zipRule.Temporary(snapshotOutputList)
884
885 zipRule.Command().
886 BuiltTool(ctx, "soong_zip").
887 FlagWithOutput("-o ", zipPath).
888 FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
889 FlagWithInput("-l ", snapshotOutputList)
890
891 zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String())
892 zipRule.DeleteTemporaryFiles()
893 c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath)
894}
895
896func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
897 ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String())
898}
Inseob Kimeec88e12020-01-22 11:11:29 +0900899
900type snapshotInterface interface {
901 matchesWithDevice(config android.DeviceConfig) bool
902}
903
904var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
905var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
906var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
Inseob Kim1042d292020-06-01 23:23:05 +0900907var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil)
Inseob Kimeec88e12020-01-22 11:11:29 +0900908
909// gathers all snapshot modules for vendor, and disable unnecessary snapshots
910// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
911func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
912 vndkVersion := ctx.DeviceConfig().VndkVersion()
913 // don't need snapshot if current
914 if vndkVersion == "current" || vndkVersion == "" {
915 return
916 }
917
918 module, ok := ctx.Module().(*Module)
919 if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion {
920 return
921 }
922
Inseob Kim1042d292020-06-01 23:23:05 +0900923 if !module.isSnapshotPrebuilt() {
Inseob Kimeec88e12020-01-22 11:11:29 +0900924 return
925 }
926
Inseob Kim1042d292020-06-01 23:23:05 +0900927 // isSnapshotPrebuilt ensures snapshotInterface
928 if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) {
Inseob Kimeec88e12020-01-22 11:11:29 +0900929 // Disable unnecessary snapshot module, but do not disable
930 // vndk_prebuilt_shared because they might be packed into vndk APEX
931 if !module.IsVndk() {
932 module.Disable()
933 }
934 return
935 }
936
937 var snapshotMap *snapshotMap
938
939 if lib, ok := module.linker.(libraryInterface); ok {
940 if lib.static() {
941 snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
942 } else if lib.shared() {
943 snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
944 } else {
945 // header
946 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
947 }
948 } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
949 snapshotMap = vendorSnapshotBinaries(ctx.Config())
Inseob Kim1042d292020-06-01 23:23:05 +0900950 } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok {
951 snapshotMap = vendorSnapshotObjects(ctx.Config())
Inseob Kimeec88e12020-01-22 11:11:29 +0900952 } else {
953 return
954 }
955
956 vendorSnapshotsLock.Lock()
957 defer vendorSnapshotsLock.Unlock()
958 snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
959}
960
961// Disables source modules which have snapshots
962func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
Inseob Kim5f64aec2020-02-18 17:27:19 +0900963 if !ctx.Device() {
964 return
965 }
966
Inseob Kimeec88e12020-01-22 11:11:29 +0900967 vndkVersion := ctx.DeviceConfig().VndkVersion()
968 // don't need snapshot if current
969 if vndkVersion == "current" || vndkVersion == "" {
970 return
971 }
972
973 module, ok := ctx.Module().(*Module)
974 if !ok {
975 return
976 }
977
Inseob Kim5f64aec2020-02-18 17:27:19 +0900978 // vendor suffix should be added to snapshots if the source module isn't vendor: true.
979 if !module.SocSpecific() {
980 // But we can't just check SocSpecific() since we already passed the image mutator.
981 // Check ramdisk and recovery to see if we are real "vendor: true" module.
982 ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk()
983 recovery_available := module.InRecovery() && !module.OnlyInRecovery()
Inseob Kimeec88e12020-01-22 11:11:29 +0900984
Inseob Kim5f64aec2020-02-18 17:27:19 +0900985 if !ramdisk_available && !recovery_available {
986 vendorSnapshotsLock.Lock()
987 defer vendorSnapshotsLock.Unlock()
988
989 vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true
990 }
Inseob Kimeec88e12020-01-22 11:11:29 +0900991 }
992
993 if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() {
994 // only non-snapshot modules with BOARD_VNDK_VERSION
995 return
996 }
997
Inseob Kim206665c2020-06-02 23:48:32 +0900998 // .. and also filter out llndk library
999 if module.isLlndk(ctx.Config()) {
1000 return
1001 }
1002
Inseob Kimeec88e12020-01-22 11:11:29 +09001003 var snapshotMap *snapshotMap
1004
1005 if lib, ok := module.linker.(libraryInterface); ok {
1006 if lib.static() {
1007 snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
1008 } else if lib.shared() {
1009 snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
1010 } else {
1011 // header
1012 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
1013 }
Inseob Kim7f283f42020-06-01 21:53:49 +09001014 } else if module.binary() {
Inseob Kimeec88e12020-01-22 11:11:29 +09001015 snapshotMap = vendorSnapshotBinaries(ctx.Config())
Inseob Kim1042d292020-06-01 23:23:05 +09001016 } else if module.object() {
1017 snapshotMap = vendorSnapshotObjects(ctx.Config())
Inseob Kimeec88e12020-01-22 11:11:29 +09001018 } else {
1019 return
1020 }
1021
1022 if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok {
1023 // Corresponding snapshot doesn't exist
1024 return
1025 }
1026
1027 // Disables source modules if corresponding snapshot exists.
1028 if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() {
1029 // But do not disable because the shared variant depends on the static variant.
1030 module.SkipInstall()
1031 module.Properties.HideFromMake = true
1032 } else {
1033 module.Disable()
1034 }
1035}