blob: 6df940c7946c5e263171fd6d1b9245f92b8859d7 [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 Kimeec88e12020-01-22 11:11:29 +090083type vendorSnapshotLibraryProperties struct {
84 // snapshot version.
85 Version string
86
87 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
88 Target_arch string
89
90 // Prebuilt file for each arch.
91 Src *string `android:"arch_variant"`
92
93 // list of flags that will be used for any module that links against this module.
94 Export_flags []string `android:"arch_variant"`
95
96 // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined symbols,
97 // etc).
98 Check_elf_files *bool
99
100 // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
101 Sanitize_ubsan_dep *bool `android:"arch_variant"`
102
103 // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
104 Sanitize_minimal_dep *bool `android:"arch_variant"`
105}
106
107type vendorSnapshotLibraryDecorator struct {
108 *libraryDecorator
109 properties vendorSnapshotLibraryProperties
110 androidMkVendorSuffix bool
111}
112
113func (p *vendorSnapshotLibraryDecorator) Name(name string) string {
114 return name + p.NameSuffix()
115}
116
117func (p *vendorSnapshotLibraryDecorator) NameSuffix() string {
118 versionSuffix := p.version()
119 if p.arch() != "" {
120 versionSuffix += "." + p.arch()
121 }
122
123 var linkageSuffix string
124 if p.buildShared() {
125 linkageSuffix = vendorSnapshotSharedSuffix
126 } else if p.buildStatic() {
127 linkageSuffix = vendorSnapshotStaticSuffix
128 } else {
129 linkageSuffix = vendorSnapshotHeaderSuffix
130 }
131
132 return linkageSuffix + versionSuffix
133}
134
135func (p *vendorSnapshotLibraryDecorator) version() string {
136 return p.properties.Version
137}
138
139func (p *vendorSnapshotLibraryDecorator) arch() string {
140 return p.properties.Target_arch
141}
142
143func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
144 p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
145 return p.libraryDecorator.linkerFlags(ctx, flags)
146}
147
148func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
149 arches := config.Arches()
150 if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
151 return false
152 }
153 if !p.header() && p.properties.Src == nil {
154 return false
155 }
156 return true
157}
158
159func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
160 flags Flags, deps PathDeps, objs Objects) android.Path {
161 m := ctx.Module().(*Module)
162 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
163
164 if p.header() {
165 return p.libraryDecorator.link(ctx, flags, deps, objs)
166 }
167
168 if !p.matchesWithDevice(ctx.DeviceConfig()) {
169 return nil
170 }
171
172 p.libraryDecorator.exportIncludes(ctx)
173 p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
174
175 in := android.PathForModuleSrc(ctx, *p.properties.Src)
176 p.unstrippedOutputFile = in
177
178 if p.shared() {
179 libName := in.Base()
180 builderFlags := flagsToBuilderFlags(flags)
181
182 // Optimize out relinking against shared libraries whose interface hasn't changed by
183 // depending on a table of contents file instead of the library itself.
184 tocFile := android.PathForModuleOut(ctx, libName+".toc")
185 p.tocFile = android.OptionalPathForPath(tocFile)
186 TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
187 }
188
189 return in
190}
191
192func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
193 return false
194}
195
Inseob Kim1042d292020-06-01 23:23:05 +0900196func (p *vendorSnapshotLibraryDecorator) isSnapshotPrebuilt() bool {
197 return true
198}
199
Inseob Kimeec88e12020-01-22 11:11:29 +0900200func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
201 if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
202 p.baseInstaller.install(ctx, file)
203 }
204}
205
206type vendorSnapshotInterface interface {
207 version() string
208}
209
210func vendorSnapshotLoadHook(ctx android.LoadHookContext, p vendorSnapshotInterface) {
211 if p.version() != ctx.DeviceConfig().VndkVersion() {
212 ctx.Module().Disable()
213 return
214 }
215}
216
217func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) {
218 module, library := NewLibrary(android.DeviceSupported)
219
220 module.stl = nil
221 module.sanitize = nil
222 library.StripProperties.Strip.None = BoolPtr(true)
223
224 prebuilt := &vendorSnapshotLibraryDecorator{
225 libraryDecorator: library,
226 }
227
228 prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
229 prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
230
231 // Prevent default system libs (libc, libm, and libdl) from being linked
232 if prebuilt.baseLinker.Properties.System_shared_libs == nil {
233 prebuilt.baseLinker.Properties.System_shared_libs = []string{}
234 }
235
236 module.compiler = nil
237 module.linker = prebuilt
238 module.installer = prebuilt
239
240 module.AddProperties(
241 &prebuilt.properties,
242 )
243
244 return module, prebuilt
245}
246
247func VendorSnapshotSharedFactory() android.Module {
248 module, prebuilt := vendorSnapshotLibrary()
249 prebuilt.libraryDecorator.BuildOnlyShared()
250 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
251 vendorSnapshotLoadHook(ctx, prebuilt)
252 })
253 return module.Init()
254}
255
256func VendorSnapshotStaticFactory() android.Module {
257 module, prebuilt := vendorSnapshotLibrary()
258 prebuilt.libraryDecorator.BuildOnlyStatic()
259 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
260 vendorSnapshotLoadHook(ctx, prebuilt)
261 })
262 return module.Init()
263}
264
265func VendorSnapshotHeaderFactory() android.Module {
266 module, prebuilt := vendorSnapshotLibrary()
267 prebuilt.libraryDecorator.HeaderOnly()
268 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
269 vendorSnapshotLoadHook(ctx, prebuilt)
270 })
271 return module.Init()
272}
273
274type vendorSnapshotBinaryProperties struct {
275 // snapshot version.
276 Version string
277
278 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
279 Target_arch string
280
281 // Prebuilt file for each arch.
282 Src *string `android:"arch_variant"`
283}
284
285type vendorSnapshotBinaryDecorator struct {
286 *binaryDecorator
287 properties vendorSnapshotBinaryProperties
288 androidMkVendorSuffix bool
289}
290
291func (p *vendorSnapshotBinaryDecorator) Name(name string) string {
292 return name + p.NameSuffix()
293}
294
295func (p *vendorSnapshotBinaryDecorator) NameSuffix() string {
296 versionSuffix := p.version()
297 if p.arch() != "" {
298 versionSuffix += "." + p.arch()
299 }
300 return vendorSnapshotBinarySuffix + versionSuffix
301}
302
303func (p *vendorSnapshotBinaryDecorator) version() string {
304 return p.properties.Version
305}
306
307func (p *vendorSnapshotBinaryDecorator) arch() string {
308 return p.properties.Target_arch
309}
310
311func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
312 if config.DeviceArch() != p.arch() {
313 return false
314 }
315 if p.properties.Src == nil {
316 return false
317 }
318 return true
319}
320
321func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
322 flags Flags, deps PathDeps, objs Objects) android.Path {
323 if !p.matchesWithDevice(ctx.DeviceConfig()) {
324 return nil
325 }
326
327 in := android.PathForModuleSrc(ctx, *p.properties.Src)
328 builderFlags := flagsToBuilderFlags(flags)
329 p.unstrippedOutputFile = in
330 binName := in.Base()
331 if p.needsStrip(ctx) {
332 stripped := android.PathForModuleOut(ctx, "stripped", binName)
333 p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
334 in = stripped
335 }
336
337 m := ctx.Module().(*Module)
338 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
339
340 // use cpExecutable to make it executable
341 outputFile := android.PathForModuleOut(ctx, binName)
342 ctx.Build(pctx, android.BuildParams{
343 Rule: android.CpExecutable,
344 Description: "prebuilt",
345 Output: outputFile,
346 Input: in,
347 })
348
349 return outputFile
350}
351
Inseob Kim1042d292020-06-01 23:23:05 +0900352func (p *vendorSnapshotBinaryDecorator) isSnapshotPrebuilt() bool {
353 return true
354}
355
Inseob Kimeec88e12020-01-22 11:11:29 +0900356func VendorSnapshotBinaryFactory() android.Module {
357 module, binary := NewBinary(android.DeviceSupported)
358 binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
359 binary.baseLinker.Properties.Nocrt = BoolPtr(true)
360
361 // Prevent default system libs (libc, libm, and libdl) from being linked
362 if binary.baseLinker.Properties.System_shared_libs == nil {
363 binary.baseLinker.Properties.System_shared_libs = []string{}
364 }
365
366 prebuilt := &vendorSnapshotBinaryDecorator{
367 binaryDecorator: binary,
368 }
369
370 module.compiler = nil
371 module.sanitize = nil
372 module.stl = nil
373 module.linker = prebuilt
374
375 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
376 vendorSnapshotLoadHook(ctx, prebuilt)
377 })
378
379 module.AddProperties(&prebuilt.properties)
380 return module.Init()
381}
382
Inseob Kim1042d292020-06-01 23:23:05 +0900383type vendorSnapshotObjectProperties struct {
384 // snapshot version.
385 Version string
386
387 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
388 Target_arch string
389
390 // Prebuilt file for each arch.
391 Src *string `android:"arch_variant"`
392}
393
394type vendorSnapshotObjectLinker struct {
395 objectLinker
396 properties vendorSnapshotObjectProperties
397 androidMkVendorSuffix bool
398}
399
400func (p *vendorSnapshotObjectLinker) Name(name string) string {
401 return name + p.NameSuffix()
402}
403
404func (p *vendorSnapshotObjectLinker) NameSuffix() string {
405 versionSuffix := p.version()
406 if p.arch() != "" {
407 versionSuffix += "." + p.arch()
408 }
409 return vendorSnapshotObjectSuffix + versionSuffix
410}
411
412func (p *vendorSnapshotObjectLinker) version() string {
413 return p.properties.Version
414}
415
416func (p *vendorSnapshotObjectLinker) arch() string {
417 return p.properties.Target_arch
418}
419
420func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
421 if config.DeviceArch() != p.arch() {
422 return false
423 }
424 if p.properties.Src == nil {
425 return false
426 }
427 return true
428}
429
430func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext,
431 flags Flags, deps PathDeps, objs Objects) android.Path {
432 if !p.matchesWithDevice(ctx.DeviceConfig()) {
433 return nil
434 }
435
436 m := ctx.Module().(*Module)
437 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
438
439 return android.PathForModuleSrc(ctx, *p.properties.Src)
440}
441
442func (p *vendorSnapshotObjectLinker) nativeCoverage() bool {
443 return false
444}
445
446func (p *vendorSnapshotObjectLinker) isSnapshotPrebuilt() bool {
447 return true
448}
449
450func VendorSnapshotObjectFactory() android.Module {
451 module := newObject()
452
453 prebuilt := &vendorSnapshotObjectLinker{
454 objectLinker: objectLinker{
455 baseLinker: NewBaseLinker(nil),
456 },
457 }
458 module.linker = prebuilt
459
460 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
461 vendorSnapshotLoadHook(ctx, prebuilt)
462 })
463
464 module.AddProperties(&prebuilt.properties)
465 return module.Init()
466}
467
Inseob Kim8471cda2019-11-15 09:59:12 +0900468func init() {
469 android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
Inseob Kimeec88e12020-01-22 11:11:29 +0900470 android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
471 android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
472 android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
473 android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
Inseob Kim1042d292020-06-01 23:23:05 +0900474 android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
Inseob Kim8471cda2019-11-15 09:59:12 +0900475}
476
477func VendorSnapshotSingleton() android.Singleton {
478 return &vendorSnapshotSingleton{}
479}
480
481type vendorSnapshotSingleton struct {
482 vendorSnapshotZipFile android.OptionalPath
483}
484
485var (
486 // Modules under following directories are ignored. They are OEM's and vendor's
Daniel Norman713387d2020-07-28 16:04:38 -0700487 // proprietary modules(device/, kernel/, vendor/, and hardware/).
Inseob Kim8471cda2019-11-15 09:59:12 +0900488 // TODO(b/65377115): Clean up these with more maintainable way
489 vendorProprietaryDirs = []string{
490 "device",
Daniel Norman713387d2020-07-28 16:04:38 -0700491 "kernel",
Inseob Kim8471cda2019-11-15 09:59:12 +0900492 "vendor",
493 "hardware",
494 }
495
496 // Modules under following directories are included as they are in AOSP,
Daniel Norman713387d2020-07-28 16:04:38 -0700497 // although hardware/ and kernel/ are normally for vendor's own.
Inseob Kim8471cda2019-11-15 09:59:12 +0900498 // TODO(b/65377115): Clean up these with more maintainable way
499 aospDirsUnderProprietary = []string{
Daniel Norman713387d2020-07-28 16:04:38 -0700500 "kernel/configs",
501 "kernel/prebuilts",
502 "kernel/tests",
Inseob Kim8471cda2019-11-15 09:59:12 +0900503 "hardware/interfaces",
504 "hardware/libhardware",
505 "hardware/libhardware_legacy",
506 "hardware/ril",
507 }
508)
509
510// Determine if a dir under source tree is an SoC-owned proprietary directory, such as
511// device/, vendor/, etc.
512func isVendorProprietaryPath(dir string) bool {
513 for _, p := range vendorProprietaryDirs {
514 if strings.HasPrefix(dir, p) {
515 // filter out AOSP defined directories, e.g. hardware/interfaces/
516 aosp := false
517 for _, p := range aospDirsUnderProprietary {
518 if strings.HasPrefix(dir, p) {
519 aosp = true
520 break
521 }
522 }
523 if !aosp {
524 return true
525 }
526 }
527 }
528 return false
529}
530
531// Determine if a module is going to be included in vendor snapshot or not.
532//
533// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
534// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
535// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
536// image and newer system image altogether.
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900537func isVendorSnapshotModule(m *Module, moduleDir string) bool {
Inseob Kim7f283f42020-06-01 21:53:49 +0900538 if !m.Enabled() || m.Properties.HideFromMake {
Inseob Kim8471cda2019-11-15 09:59:12 +0900539 return false
540 }
541 // skip proprietary modules, but include all VNDK (static)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900542 if isVendorProprietaryPath(moduleDir) && !m.IsVndk() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900543 return false
544 }
545 if m.Target().Os.Class != android.Device {
546 return false
547 }
548 if m.Target().NativeBridge == android.NativeBridgeEnabled {
549 return false
550 }
551 // the module must be installed in /vendor
Inseob Kim7f283f42020-06-01 21:53:49 +0900552 if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900553 return false
554 }
Inseob Kim65ca36a2020-06-11 13:55:45 +0900555 // skip kernel_headers which always depend on vendor
556 if _, ok := m.linker.(*kernelHeadersDecorator); ok {
557 return false
558 }
Justin Yunf2664c62020-07-30 18:57:54 +0900559 // skip llndk_library and llndk_headers which are backward compatible
560 if _, ok := m.linker.(*llndkStubDecorator); ok {
561 return false
562 }
563 if _, ok := m.linker.(*llndkHeadersDecorator); ok {
564 return false
565 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900566
567 // Libraries
568 if l, ok := m.linker.(snapshotLibraryInterface); ok {
Inseob Kim7f283f42020-06-01 21:53:49 +0900569 // TODO(b/65377115): add full support for sanitizer
570 if m.sanitize != nil {
571 // cfi, scs and hwasan export both sanitized and unsanitized variants for static and header
572 // Always use unsanitized variants of them.
573 for _, t := range []sanitizerType{cfi, scs, hwasan} {
574 if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
575 return false
576 }
577 }
578 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900579 if l.static() {
Inseob Kim7f283f42020-06-01 21:53:49 +0900580 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
Inseob Kim8471cda2019-11-15 09:59:12 +0900581 }
582 if l.shared() {
Bill Peckham7d3f0962020-06-29 16:49:15 -0700583 if !m.outputFile.Valid() {
584 return false
585 }
586 if !m.IsVndk() {
587 return true
588 }
589 return m.isVndkExt()
Inseob Kim8471cda2019-11-15 09:59:12 +0900590 }
591 return true
592 }
593
Inseob Kim1042d292020-06-01 23:23:05 +0900594 // Binaries and Objects
595 if m.binary() || m.object() {
Inseob Kim7f283f42020-06-01 21:53:49 +0900596 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
Inseob Kim8471cda2019-11-15 09:59:12 +0900597 }
Inseob Kim7f283f42020-06-01 21:53:49 +0900598
599 return false
Inseob Kim8471cda2019-11-15 09:59:12 +0900600}
601
602func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
603 // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
604 if ctx.DeviceConfig().VndkVersion() != "current" {
605 return
606 }
607
608 var snapshotOutputs android.Paths
609
610 /*
611 Vendor snapshot zipped artifacts directory structure:
612 {SNAPSHOT_ARCH}/
613 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
614 shared/
615 (.so shared libraries)
616 static/
617 (.a static libraries)
618 header/
619 (header only libraries)
620 binary/
621 (executable binaries)
Inseob Kim1042d292020-06-01 23:23:05 +0900622 object/
623 (.o object files)
Inseob Kim8471cda2019-11-15 09:59:12 +0900624 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
625 shared/
626 (.so shared libraries)
627 static/
628 (.a static libraries)
629 header/
630 (header only libraries)
631 binary/
632 (executable binaries)
Inseob Kim1042d292020-06-01 23:23:05 +0900633 object/
634 (.o object files)
Inseob Kim8471cda2019-11-15 09:59:12 +0900635 NOTICE_FILES/
636 (notice files, e.g. libbase.txt)
637 configs/
638 (config files, e.g. init.rc files, vintf_fragments.xml files, etc.)
639 include/
640 (header files of same directory structure with source tree)
641 */
642
643 snapshotDir := "vendor-snapshot"
644 snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
645
646 includeDir := filepath.Join(snapshotArchDir, "include")
647 configsDir := filepath.Join(snapshotArchDir, "configs")
648 noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
649
650 installedNotices := make(map[string]bool)
651 installedConfigs := make(map[string]bool)
652
653 var headers android.Paths
654
Inseob Kim8471cda2019-11-15 09:59:12 +0900655 installSnapshot := func(m *Module) android.Paths {
656 targetArch := "arch-" + m.Target().Arch.ArchType.String()
657 if m.Target().Arch.ArchVariant != "" {
658 targetArch += "-" + m.Target().Arch.ArchVariant
659 }
660
661 var ret android.Paths
662
663 prop := struct {
664 ModuleName string `json:",omitempty"`
665 RelativeInstallPath string `json:",omitempty"`
666
667 // library flags
668 ExportedDirs []string `json:",omitempty"`
669 ExportedSystemDirs []string `json:",omitempty"`
670 ExportedFlags []string `json:",omitempty"`
671 SanitizeMinimalDep bool `json:",omitempty"`
672 SanitizeUbsanDep bool `json:",omitempty"`
673
674 // binary flags
675 Symlinks []string `json:",omitempty"`
676
677 // dependencies
678 SharedLibs []string `json:",omitempty"`
679 RuntimeLibs []string `json:",omitempty"`
680 Required []string `json:",omitempty"`
681
682 // extra config files
683 InitRc []string `json:",omitempty"`
684 VintfFragments []string `json:",omitempty"`
685 }{}
686
687 // Common properties among snapshots.
688 prop.ModuleName = ctx.ModuleName(m)
Bill Peckham7d3f0962020-06-29 16:49:15 -0700689 if m.isVndkExt() {
690 // vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
691 if m.isVndkSp() {
692 prop.RelativeInstallPath = "vndk-sp"
693 } else {
694 prop.RelativeInstallPath = "vndk"
695 }
696 } else {
697 prop.RelativeInstallPath = m.RelativeInstallPath()
698 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900699 prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs
700 prop.Required = m.RequiredModuleNames()
701 for _, path := range m.InitRc() {
702 prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base()))
703 }
704 for _, path := range m.VintfFragments() {
705 prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base()))
706 }
707
708 // install config files. ignores any duplicates.
709 for _, path := range append(m.InitRc(), m.VintfFragments()...) {
710 out := filepath.Join(configsDir, path.Base())
711 if !installedConfigs[out] {
712 installedConfigs[out] = true
713 ret = append(ret, copyFile(ctx, path, out))
714 }
715 }
716
717 var propOut string
718
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900719 if l, ok := m.linker.(snapshotLibraryInterface); ok {
Inseob Kim8471cda2019-11-15 09:59:12 +0900720 // library flags
721 prop.ExportedFlags = l.exportedFlags()
722 for _, dir := range l.exportedDirs() {
723 prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String()))
724 }
725 for _, dir := range l.exportedSystemDirs() {
726 prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String()))
727 }
728 // shared libs dependencies aren't meaningful on static or header libs
729 if l.shared() {
730 prop.SharedLibs = m.Properties.SnapshotSharedLibs
731 }
732 if l.static() && m.sanitize != nil {
733 prop.SanitizeMinimalDep = m.sanitize.Properties.MinimalRuntimeDep || enableMinimalRuntime(m.sanitize)
734 prop.SanitizeUbsanDep = m.sanitize.Properties.UbsanRuntimeDep || enableUbsanRuntime(m.sanitize)
735 }
736
737 var libType string
738 if l.static() {
739 libType = "static"
740 } else if l.shared() {
741 libType = "shared"
742 } else {
743 libType = "header"
744 }
745
746 var stem string
747
748 // install .a or .so
749 if libType != "header" {
750 libPath := m.outputFile.Path()
751 stem = libPath.Base()
752 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
753 ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
754 } else {
755 stem = ctx.ModuleName(m)
756 }
757
758 propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json")
Inseob Kim7f283f42020-06-01 21:53:49 +0900759 } else if m.binary() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900760 // binary flags
761 prop.Symlinks = m.Symlinks()
762 prop.SharedLibs = m.Properties.SnapshotSharedLibs
763
764 // install bin
765 binPath := m.outputFile.Path()
766 snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
767 ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
768 propOut = snapshotBinOut + ".json"
Inseob Kim1042d292020-06-01 23:23:05 +0900769 } else if m.object() {
770 // object files aren't installed to the device, so their names can conflict.
771 // Use module name as stem.
772 objPath := m.outputFile.Path()
773 snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
774 ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
775 ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
776 propOut = snapshotObjOut + ".json"
Inseob Kim7f283f42020-06-01 21:53:49 +0900777 } else {
778 ctx.Errorf("unknown module %q in vendor snapshot", m.String())
779 return nil
Inseob Kim8471cda2019-11-15 09:59:12 +0900780 }
781
782 j, err := json.Marshal(prop)
783 if err != nil {
784 ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
785 return nil
786 }
787 ret = append(ret, writeStringToFile(ctx, string(j), propOut))
788
789 return ret
790 }
791
792 ctx.VisitAllModules(func(module android.Module) {
793 m, ok := module.(*Module)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900794 if !ok {
795 return
796 }
797
798 moduleDir := ctx.ModuleDir(module)
799 if !isVendorSnapshotModule(m, moduleDir) {
Inseob Kim8471cda2019-11-15 09:59:12 +0900800 return
801 }
802
803 snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900804 if l, ok := m.linker.(snapshotLibraryInterface); ok {
805 headers = append(headers, l.snapshotHeaders()...)
Inseob Kim8471cda2019-11-15 09:59:12 +0900806 }
807
Bob Badoura75b0572020-02-18 20:21:55 -0800808 if len(m.NoticeFiles()) > 0 {
Inseob Kim8471cda2019-11-15 09:59:12 +0900809 noticeName := ctx.ModuleName(m) + ".txt"
810 noticeOut := filepath.Join(noticeDir, noticeName)
811 // skip already copied notice file
812 if !installedNotices[noticeOut] {
813 installedNotices[noticeOut] = true
Bob Badoura75b0572020-02-18 20:21:55 -0800814 snapshotOutputs = append(snapshotOutputs, combineNotices(
815 ctx, m.NoticeFiles(), noticeOut))
Inseob Kim8471cda2019-11-15 09:59:12 +0900816 }
817 }
818 })
819
820 // install all headers after removing duplicates
821 for _, header := range android.FirstUniquePaths(headers) {
822 snapshotOutputs = append(snapshotOutputs, copyFile(
823 ctx, header, filepath.Join(includeDir, header.String())))
824 }
825
826 // All artifacts are ready. Sort them to normalize ninja and then zip.
827 sort.Slice(snapshotOutputs, func(i, j int) bool {
828 return snapshotOutputs[i].String() < snapshotOutputs[j].String()
829 })
830
831 zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip")
832 zipRule := android.NewRuleBuilder()
833
834 // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
835 snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list")
836 zipRule.Command().
837 Text("tr").
838 FlagWithArg("-d ", "\\'").
839 FlagWithRspFileInputList("< ", snapshotOutputs).
840 FlagWithOutput("> ", snapshotOutputList)
841
842 zipRule.Temporary(snapshotOutputList)
843
844 zipRule.Command().
845 BuiltTool(ctx, "soong_zip").
846 FlagWithOutput("-o ", zipPath).
847 FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
848 FlagWithInput("-l ", snapshotOutputList)
849
850 zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String())
851 zipRule.DeleteTemporaryFiles()
852 c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath)
853}
854
855func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
856 ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String())
857}
Inseob Kimeec88e12020-01-22 11:11:29 +0900858
859type snapshotInterface interface {
860 matchesWithDevice(config android.DeviceConfig) bool
861}
862
863var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
864var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
865var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
Inseob Kim1042d292020-06-01 23:23:05 +0900866var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil)
Inseob Kimeec88e12020-01-22 11:11:29 +0900867
868// gathers all snapshot modules for vendor, and disable unnecessary snapshots
869// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
870func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
871 vndkVersion := ctx.DeviceConfig().VndkVersion()
872 // don't need snapshot if current
873 if vndkVersion == "current" || vndkVersion == "" {
874 return
875 }
876
877 module, ok := ctx.Module().(*Module)
878 if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion {
879 return
880 }
881
Inseob Kim1042d292020-06-01 23:23:05 +0900882 if !module.isSnapshotPrebuilt() {
Inseob Kimeec88e12020-01-22 11:11:29 +0900883 return
884 }
885
Inseob Kim1042d292020-06-01 23:23:05 +0900886 // isSnapshotPrebuilt ensures snapshotInterface
887 if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) {
Inseob Kimeec88e12020-01-22 11:11:29 +0900888 // Disable unnecessary snapshot module, but do not disable
889 // vndk_prebuilt_shared because they might be packed into vndk APEX
890 if !module.IsVndk() {
891 module.Disable()
892 }
893 return
894 }
895
896 var snapshotMap *snapshotMap
897
898 if lib, ok := module.linker.(libraryInterface); ok {
899 if lib.static() {
900 snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
901 } else if lib.shared() {
902 snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
903 } else {
904 // header
905 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
906 }
907 } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
908 snapshotMap = vendorSnapshotBinaries(ctx.Config())
Inseob Kim1042d292020-06-01 23:23:05 +0900909 } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok {
910 snapshotMap = vendorSnapshotObjects(ctx.Config())
Inseob Kimeec88e12020-01-22 11:11:29 +0900911 } else {
912 return
913 }
914
915 vendorSnapshotsLock.Lock()
916 defer vendorSnapshotsLock.Unlock()
917 snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
918}
919
920// Disables source modules which have snapshots
921func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
Inseob Kim5f64aec2020-02-18 17:27:19 +0900922 if !ctx.Device() {
923 return
924 }
925
Inseob Kimeec88e12020-01-22 11:11:29 +0900926 vndkVersion := ctx.DeviceConfig().VndkVersion()
927 // don't need snapshot if current
928 if vndkVersion == "current" || vndkVersion == "" {
929 return
930 }
931
932 module, ok := ctx.Module().(*Module)
933 if !ok {
934 return
935 }
936
Inseob Kim5f64aec2020-02-18 17:27:19 +0900937 // vendor suffix should be added to snapshots if the source module isn't vendor: true.
938 if !module.SocSpecific() {
939 // But we can't just check SocSpecific() since we already passed the image mutator.
940 // Check ramdisk and recovery to see if we are real "vendor: true" module.
941 ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk()
942 recovery_available := module.InRecovery() && !module.OnlyInRecovery()
Inseob Kimeec88e12020-01-22 11:11:29 +0900943
Inseob Kim5f64aec2020-02-18 17:27:19 +0900944 if !ramdisk_available && !recovery_available {
945 vendorSnapshotsLock.Lock()
946 defer vendorSnapshotsLock.Unlock()
947
948 vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true
949 }
Inseob Kimeec88e12020-01-22 11:11:29 +0900950 }
951
952 if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() {
953 // only non-snapshot modules with BOARD_VNDK_VERSION
954 return
955 }
956
Inseob Kim206665c2020-06-02 23:48:32 +0900957 // .. and also filter out llndk library
958 if module.isLlndk(ctx.Config()) {
959 return
960 }
961
Inseob Kimeec88e12020-01-22 11:11:29 +0900962 var snapshotMap *snapshotMap
963
964 if lib, ok := module.linker.(libraryInterface); ok {
965 if lib.static() {
966 snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
967 } else if lib.shared() {
968 snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
969 } else {
970 // header
971 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
972 }
Inseob Kim7f283f42020-06-01 21:53:49 +0900973 } else if module.binary() {
Inseob Kimeec88e12020-01-22 11:11:29 +0900974 snapshotMap = vendorSnapshotBinaries(ctx.Config())
Inseob Kim1042d292020-06-01 23:23:05 +0900975 } else if module.object() {
976 snapshotMap = vendorSnapshotObjects(ctx.Config())
Inseob Kimeec88e12020-01-22 11:11:29 +0900977 } else {
978 return
979 }
980
981 if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok {
982 // Corresponding snapshot doesn't exist
983 return
984 }
985
986 // Disables source modules if corresponding snapshot exists.
987 if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() {
988 // But do not disable because the shared variant depends on the static variant.
989 module.SkipInstall()
990 module.Properties.HideFromMake = true
991 } else {
992 module.Disable()
993 }
994}