blob: 1ff617f73e00c88209beab60c92c1ac5a0641992 [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."
33)
34
35var (
36 vendorSnapshotsLock sync.Mutex
37 vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules")
38 vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs")
39 vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs")
40 vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs")
41 vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries")
42)
43
Inseob Kim5f64aec2020-02-18 17:27:19 +090044// vendor snapshot maps hold names of vendor snapshot modules per arch
Inseob Kimeec88e12020-01-22 11:11:29 +090045func vendorSuffixModules(config android.Config) map[string]bool {
46 return config.Once(vendorSuffixModulesKey, func() interface{} {
47 return make(map[string]bool)
48 }).(map[string]bool)
49}
50
51func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap {
52 return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} {
53 return newSnapshotMap()
54 }).(*snapshotMap)
55}
56
57func vendorSnapshotSharedLibs(config android.Config) *snapshotMap {
58 return config.Once(vendorSnapshotSharedLibsKey, func() interface{} {
59 return newSnapshotMap()
60 }).(*snapshotMap)
61}
62
63func vendorSnapshotStaticLibs(config android.Config) *snapshotMap {
64 return config.Once(vendorSnapshotStaticLibsKey, func() interface{} {
65 return newSnapshotMap()
66 }).(*snapshotMap)
67}
68
69func vendorSnapshotBinaries(config android.Config) *snapshotMap {
70 return config.Once(vendorSnapshotBinariesKey, func() interface{} {
71 return newSnapshotMap()
72 }).(*snapshotMap)
73}
74
75type vendorSnapshotLibraryProperties struct {
76 // snapshot version.
77 Version string
78
79 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
80 Target_arch string
81
82 // Prebuilt file for each arch.
83 Src *string `android:"arch_variant"`
84
85 // list of flags that will be used for any module that links against this module.
86 Export_flags []string `android:"arch_variant"`
87
88 // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined symbols,
89 // etc).
90 Check_elf_files *bool
91
92 // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
93 Sanitize_ubsan_dep *bool `android:"arch_variant"`
94
95 // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
96 Sanitize_minimal_dep *bool `android:"arch_variant"`
97}
98
99type vendorSnapshotLibraryDecorator struct {
100 *libraryDecorator
101 properties vendorSnapshotLibraryProperties
102 androidMkVendorSuffix bool
103}
104
105func (p *vendorSnapshotLibraryDecorator) Name(name string) string {
106 return name + p.NameSuffix()
107}
108
109func (p *vendorSnapshotLibraryDecorator) NameSuffix() string {
110 versionSuffix := p.version()
111 if p.arch() != "" {
112 versionSuffix += "." + p.arch()
113 }
114
115 var linkageSuffix string
116 if p.buildShared() {
117 linkageSuffix = vendorSnapshotSharedSuffix
118 } else if p.buildStatic() {
119 linkageSuffix = vendorSnapshotStaticSuffix
120 } else {
121 linkageSuffix = vendorSnapshotHeaderSuffix
122 }
123
124 return linkageSuffix + versionSuffix
125}
126
127func (p *vendorSnapshotLibraryDecorator) version() string {
128 return p.properties.Version
129}
130
131func (p *vendorSnapshotLibraryDecorator) arch() string {
132 return p.properties.Target_arch
133}
134
135func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
136 p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
137 return p.libraryDecorator.linkerFlags(ctx, flags)
138}
139
140func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
141 arches := config.Arches()
142 if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
143 return false
144 }
145 if !p.header() && p.properties.Src == nil {
146 return false
147 }
148 return true
149}
150
151func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
152 flags Flags, deps PathDeps, objs Objects) android.Path {
153 m := ctx.Module().(*Module)
154 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
155
156 if p.header() {
157 return p.libraryDecorator.link(ctx, flags, deps, objs)
158 }
159
160 if !p.matchesWithDevice(ctx.DeviceConfig()) {
161 return nil
162 }
163
164 p.libraryDecorator.exportIncludes(ctx)
165 p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
166
167 in := android.PathForModuleSrc(ctx, *p.properties.Src)
168 p.unstrippedOutputFile = in
169
170 if p.shared() {
171 libName := in.Base()
172 builderFlags := flagsToBuilderFlags(flags)
173
174 // Optimize out relinking against shared libraries whose interface hasn't changed by
175 // depending on a table of contents file instead of the library itself.
176 tocFile := android.PathForModuleOut(ctx, libName+".toc")
177 p.tocFile = android.OptionalPathForPath(tocFile)
178 TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
179 }
180
181 return in
182}
183
184func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
185 return false
186}
187
188func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
189 if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
190 p.baseInstaller.install(ctx, file)
191 }
192}
193
194type vendorSnapshotInterface interface {
195 version() string
196}
197
198func vendorSnapshotLoadHook(ctx android.LoadHookContext, p vendorSnapshotInterface) {
199 if p.version() != ctx.DeviceConfig().VndkVersion() {
200 ctx.Module().Disable()
201 return
202 }
203}
204
205func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) {
206 module, library := NewLibrary(android.DeviceSupported)
207
208 module.stl = nil
209 module.sanitize = nil
210 library.StripProperties.Strip.None = BoolPtr(true)
211
212 prebuilt := &vendorSnapshotLibraryDecorator{
213 libraryDecorator: library,
214 }
215
216 prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
217 prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
218
219 // Prevent default system libs (libc, libm, and libdl) from being linked
220 if prebuilt.baseLinker.Properties.System_shared_libs == nil {
221 prebuilt.baseLinker.Properties.System_shared_libs = []string{}
222 }
223
224 module.compiler = nil
225 module.linker = prebuilt
226 module.installer = prebuilt
227
228 module.AddProperties(
229 &prebuilt.properties,
230 )
231
232 return module, prebuilt
233}
234
235func VendorSnapshotSharedFactory() android.Module {
236 module, prebuilt := vendorSnapshotLibrary()
237 prebuilt.libraryDecorator.BuildOnlyShared()
238 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
239 vendorSnapshotLoadHook(ctx, prebuilt)
240 })
241 return module.Init()
242}
243
244func VendorSnapshotStaticFactory() android.Module {
245 module, prebuilt := vendorSnapshotLibrary()
246 prebuilt.libraryDecorator.BuildOnlyStatic()
247 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
248 vendorSnapshotLoadHook(ctx, prebuilt)
249 })
250 return module.Init()
251}
252
253func VendorSnapshotHeaderFactory() android.Module {
254 module, prebuilt := vendorSnapshotLibrary()
255 prebuilt.libraryDecorator.HeaderOnly()
256 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
257 vendorSnapshotLoadHook(ctx, prebuilt)
258 })
259 return module.Init()
260}
261
262type vendorSnapshotBinaryProperties struct {
263 // snapshot version.
264 Version string
265
266 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
267 Target_arch string
268
269 // Prebuilt file for each arch.
270 Src *string `android:"arch_variant"`
271}
272
273type vendorSnapshotBinaryDecorator struct {
274 *binaryDecorator
275 properties vendorSnapshotBinaryProperties
276 androidMkVendorSuffix bool
277}
278
279func (p *vendorSnapshotBinaryDecorator) Name(name string) string {
280 return name + p.NameSuffix()
281}
282
283func (p *vendorSnapshotBinaryDecorator) NameSuffix() string {
284 versionSuffix := p.version()
285 if p.arch() != "" {
286 versionSuffix += "." + p.arch()
287 }
288 return vendorSnapshotBinarySuffix + versionSuffix
289}
290
291func (p *vendorSnapshotBinaryDecorator) version() string {
292 return p.properties.Version
293}
294
295func (p *vendorSnapshotBinaryDecorator) arch() string {
296 return p.properties.Target_arch
297}
298
299func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
300 if config.DeviceArch() != p.arch() {
301 return false
302 }
303 if p.properties.Src == nil {
304 return false
305 }
306 return true
307}
308
309func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
310 flags Flags, deps PathDeps, objs Objects) android.Path {
311 if !p.matchesWithDevice(ctx.DeviceConfig()) {
312 return nil
313 }
314
315 in := android.PathForModuleSrc(ctx, *p.properties.Src)
316 builderFlags := flagsToBuilderFlags(flags)
317 p.unstrippedOutputFile = in
318 binName := in.Base()
319 if p.needsStrip(ctx) {
320 stripped := android.PathForModuleOut(ctx, "stripped", binName)
321 p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
322 in = stripped
323 }
324
325 m := ctx.Module().(*Module)
326 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
327
328 // use cpExecutable to make it executable
329 outputFile := android.PathForModuleOut(ctx, binName)
330 ctx.Build(pctx, android.BuildParams{
331 Rule: android.CpExecutable,
332 Description: "prebuilt",
333 Output: outputFile,
334 Input: in,
335 })
336
337 return outputFile
338}
339
340func VendorSnapshotBinaryFactory() android.Module {
341 module, binary := NewBinary(android.DeviceSupported)
342 binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
343 binary.baseLinker.Properties.Nocrt = BoolPtr(true)
344
345 // Prevent default system libs (libc, libm, and libdl) from being linked
346 if binary.baseLinker.Properties.System_shared_libs == nil {
347 binary.baseLinker.Properties.System_shared_libs = []string{}
348 }
349
350 prebuilt := &vendorSnapshotBinaryDecorator{
351 binaryDecorator: binary,
352 }
353
354 module.compiler = nil
355 module.sanitize = nil
356 module.stl = nil
357 module.linker = prebuilt
358
359 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
360 vendorSnapshotLoadHook(ctx, prebuilt)
361 })
362
363 module.AddProperties(&prebuilt.properties)
364 return module.Init()
365}
366
Inseob Kim8471cda2019-11-15 09:59:12 +0900367func init() {
368 android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
Inseob Kimeec88e12020-01-22 11:11:29 +0900369 android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
370 android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
371 android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
372 android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
Inseob Kim8471cda2019-11-15 09:59:12 +0900373}
374
375func VendorSnapshotSingleton() android.Singleton {
376 return &vendorSnapshotSingleton{}
377}
378
379type vendorSnapshotSingleton struct {
380 vendorSnapshotZipFile android.OptionalPath
381}
382
383var (
384 // Modules under following directories are ignored. They are OEM's and vendor's
385 // proprietary modules(device/, vendor/, and hardware/).
386 // TODO(b/65377115): Clean up these with more maintainable way
387 vendorProprietaryDirs = []string{
388 "device",
389 "vendor",
390 "hardware",
391 }
392
393 // Modules under following directories are included as they are in AOSP,
394 // although hardware/ is normally for vendor's own.
395 // TODO(b/65377115): Clean up these with more maintainable way
396 aospDirsUnderProprietary = []string{
397 "hardware/interfaces",
398 "hardware/libhardware",
399 "hardware/libhardware_legacy",
400 "hardware/ril",
401 }
402)
403
404// Determine if a dir under source tree is an SoC-owned proprietary directory, such as
405// device/, vendor/, etc.
406func isVendorProprietaryPath(dir string) bool {
407 for _, p := range vendorProprietaryDirs {
408 if strings.HasPrefix(dir, p) {
409 // filter out AOSP defined directories, e.g. hardware/interfaces/
410 aosp := false
411 for _, p := range aospDirsUnderProprietary {
412 if strings.HasPrefix(dir, p) {
413 aosp = true
414 break
415 }
416 }
417 if !aosp {
418 return true
419 }
420 }
421 }
422 return false
423}
424
425// Determine if a module is going to be included in vendor snapshot or not.
426//
427// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
428// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
429// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
430// image and newer system image altogether.
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900431func isVendorSnapshotModule(m *Module, moduleDir string) bool {
Inseob Kim8471cda2019-11-15 09:59:12 +0900432 if !m.Enabled() {
433 return false
434 }
435 // skip proprietary modules, but include all VNDK (static)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900436 if isVendorProprietaryPath(moduleDir) && !m.IsVndk() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900437 return false
438 }
439 if m.Target().Os.Class != android.Device {
440 return false
441 }
442 if m.Target().NativeBridge == android.NativeBridgeEnabled {
443 return false
444 }
445 // the module must be installed in /vendor
Inseob Kimb6a58622020-05-20 22:53:06 +0900446 if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
Inseob Kim8471cda2019-11-15 09:59:12 +0900447 return false
448 }
449 // exclude test modules
450 if _, ok := m.linker.(interface{ gtest() bool }); ok {
451 return false
452 }
453 // TODO(b/65377115): add full support for sanitizer
454 if m.sanitize != nil && !m.sanitize.isUnsanitizedVariant() {
455 return false
456 }
457
458 // Libraries
459 if l, ok := m.linker.(snapshotLibraryInterface); ok {
Inseob Kimb6a58622020-05-20 22:53:06 +0900460 // header libraries are not installable, but captured.
461 if (l.static() || l.shared()) && !m.installable() {
462 return false
463 }
Inseob Kim8471cda2019-11-15 09:59:12 +0900464 if l.static() {
465 return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
466 }
467 if l.shared() {
468 return !m.IsVndk()
469 }
Inseob Kimb6a58622020-05-20 22:53:06 +0900470
Inseob Kim8471cda2019-11-15 09:59:12 +0900471 return true
472 }
473
474 // Binaries
475 _, ok := m.linker.(*binaryDecorator)
476 if !ok {
477 if _, ok := m.linker.(*prebuiltBinaryLinker); !ok {
478 return false
479 }
480 }
481 return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
482}
483
484func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
485 // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
486 if ctx.DeviceConfig().VndkVersion() != "current" {
487 return
488 }
489
490 var snapshotOutputs android.Paths
491
492 /*
493 Vendor snapshot zipped artifacts directory structure:
494 {SNAPSHOT_ARCH}/
495 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
496 shared/
497 (.so shared libraries)
498 static/
499 (.a static libraries)
500 header/
501 (header only libraries)
502 binary/
503 (executable binaries)
504 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
505 shared/
506 (.so shared libraries)
507 static/
508 (.a static libraries)
509 header/
510 (header only libraries)
511 binary/
512 (executable binaries)
513 NOTICE_FILES/
514 (notice files, e.g. libbase.txt)
515 configs/
516 (config files, e.g. init.rc files, vintf_fragments.xml files, etc.)
517 include/
518 (header files of same directory structure with source tree)
519 */
520
521 snapshotDir := "vendor-snapshot"
522 snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
523
524 includeDir := filepath.Join(snapshotArchDir, "include")
525 configsDir := filepath.Join(snapshotArchDir, "configs")
526 noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
527
528 installedNotices := make(map[string]bool)
529 installedConfigs := make(map[string]bool)
530
531 var headers android.Paths
532
Inseob Kim8471cda2019-11-15 09:59:12 +0900533 installSnapshot := func(m *Module) android.Paths {
534 targetArch := "arch-" + m.Target().Arch.ArchType.String()
535 if m.Target().Arch.ArchVariant != "" {
536 targetArch += "-" + m.Target().Arch.ArchVariant
537 }
538
539 var ret android.Paths
540
541 prop := struct {
542 ModuleName string `json:",omitempty"`
543 RelativeInstallPath string `json:",omitempty"`
544
545 // library flags
546 ExportedDirs []string `json:",omitempty"`
547 ExportedSystemDirs []string `json:",omitempty"`
548 ExportedFlags []string `json:",omitempty"`
549 SanitizeMinimalDep bool `json:",omitempty"`
550 SanitizeUbsanDep bool `json:",omitempty"`
551
552 // binary flags
553 Symlinks []string `json:",omitempty"`
554
555 // dependencies
556 SharedLibs []string `json:",omitempty"`
557 RuntimeLibs []string `json:",omitempty"`
558 Required []string `json:",omitempty"`
559
560 // extra config files
561 InitRc []string `json:",omitempty"`
562 VintfFragments []string `json:",omitempty"`
563 }{}
564
565 // Common properties among snapshots.
566 prop.ModuleName = ctx.ModuleName(m)
567 prop.RelativeInstallPath = m.RelativeInstallPath()
568 prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs
569 prop.Required = m.RequiredModuleNames()
570 for _, path := range m.InitRc() {
571 prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base()))
572 }
573 for _, path := range m.VintfFragments() {
574 prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base()))
575 }
576
577 // install config files. ignores any duplicates.
578 for _, path := range append(m.InitRc(), m.VintfFragments()...) {
579 out := filepath.Join(configsDir, path.Base())
580 if !installedConfigs[out] {
581 installedConfigs[out] = true
582 ret = append(ret, copyFile(ctx, path, out))
583 }
584 }
585
586 var propOut string
587
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900588 if l, ok := m.linker.(snapshotLibraryInterface); ok {
Inseob Kim8471cda2019-11-15 09:59:12 +0900589 // library flags
590 prop.ExportedFlags = l.exportedFlags()
591 for _, dir := range l.exportedDirs() {
592 prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String()))
593 }
594 for _, dir := range l.exportedSystemDirs() {
595 prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String()))
596 }
597 // shared libs dependencies aren't meaningful on static or header libs
598 if l.shared() {
599 prop.SharedLibs = m.Properties.SnapshotSharedLibs
600 }
601 if l.static() && m.sanitize != nil {
602 prop.SanitizeMinimalDep = m.sanitize.Properties.MinimalRuntimeDep || enableMinimalRuntime(m.sanitize)
603 prop.SanitizeUbsanDep = m.sanitize.Properties.UbsanRuntimeDep || enableUbsanRuntime(m.sanitize)
604 }
605
606 var libType string
607 if l.static() {
608 libType = "static"
609 } else if l.shared() {
610 libType = "shared"
611 } else {
612 libType = "header"
613 }
614
615 var stem string
616
617 // install .a or .so
618 if libType != "header" {
619 libPath := m.outputFile.Path()
620 stem = libPath.Base()
621 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
622 ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
623 } else {
624 stem = ctx.ModuleName(m)
625 }
626
627 propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json")
628 } else {
629 // binary flags
630 prop.Symlinks = m.Symlinks()
631 prop.SharedLibs = m.Properties.SnapshotSharedLibs
632
633 // install bin
634 binPath := m.outputFile.Path()
635 snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
636 ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
637 propOut = snapshotBinOut + ".json"
638 }
639
640 j, err := json.Marshal(prop)
641 if err != nil {
642 ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
643 return nil
644 }
645 ret = append(ret, writeStringToFile(ctx, string(j), propOut))
646
647 return ret
648 }
649
650 ctx.VisitAllModules(func(module android.Module) {
651 m, ok := module.(*Module)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900652 if !ok {
653 return
654 }
655
656 moduleDir := ctx.ModuleDir(module)
657 if !isVendorSnapshotModule(m, moduleDir) {
Inseob Kim8471cda2019-11-15 09:59:12 +0900658 return
659 }
660
661 snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...)
Inseob Kimeda2e9c2020-03-03 22:06:32 +0900662 if l, ok := m.linker.(snapshotLibraryInterface); ok {
663 headers = append(headers, l.snapshotHeaders()...)
Inseob Kim8471cda2019-11-15 09:59:12 +0900664 }
665
Bob Badoura75b0572020-02-18 20:21:55 -0800666 if len(m.NoticeFiles()) > 0 {
Inseob Kim8471cda2019-11-15 09:59:12 +0900667 noticeName := ctx.ModuleName(m) + ".txt"
668 noticeOut := filepath.Join(noticeDir, noticeName)
669 // skip already copied notice file
670 if !installedNotices[noticeOut] {
671 installedNotices[noticeOut] = true
Bob Badoura75b0572020-02-18 20:21:55 -0800672 snapshotOutputs = append(snapshotOutputs, combineNotices(
673 ctx, m.NoticeFiles(), noticeOut))
Inseob Kim8471cda2019-11-15 09:59:12 +0900674 }
675 }
676 })
677
678 // install all headers after removing duplicates
679 for _, header := range android.FirstUniquePaths(headers) {
680 snapshotOutputs = append(snapshotOutputs, copyFile(
681 ctx, header, filepath.Join(includeDir, header.String())))
682 }
683
684 // All artifacts are ready. Sort them to normalize ninja and then zip.
685 sort.Slice(snapshotOutputs, func(i, j int) bool {
686 return snapshotOutputs[i].String() < snapshotOutputs[j].String()
687 })
688
689 zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip")
690 zipRule := android.NewRuleBuilder()
691
692 // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
693 snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list")
694 zipRule.Command().
695 Text("tr").
696 FlagWithArg("-d ", "\\'").
697 FlagWithRspFileInputList("< ", snapshotOutputs).
698 FlagWithOutput("> ", snapshotOutputList)
699
700 zipRule.Temporary(snapshotOutputList)
701
702 zipRule.Command().
703 BuiltTool(ctx, "soong_zip").
704 FlagWithOutput("-o ", zipPath).
705 FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
706 FlagWithInput("-l ", snapshotOutputList)
707
708 zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String())
709 zipRule.DeleteTemporaryFiles()
710 c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath)
711}
712
713func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
714 ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String())
715}
Inseob Kimeec88e12020-01-22 11:11:29 +0900716
717type snapshotInterface interface {
718 matchesWithDevice(config android.DeviceConfig) bool
719}
720
721var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
722var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
723var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
724
725// gathers all snapshot modules for vendor, and disable unnecessary snapshots
726// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
727func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
728 vndkVersion := ctx.DeviceConfig().VndkVersion()
729 // don't need snapshot if current
730 if vndkVersion == "current" || vndkVersion == "" {
731 return
732 }
733
734 module, ok := ctx.Module().(*Module)
735 if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion {
736 return
737 }
738
739 snapshot, ok := module.linker.(snapshotInterface)
740 if !ok {
741 return
742 }
743
744 if !snapshot.matchesWithDevice(ctx.DeviceConfig()) {
745 // Disable unnecessary snapshot module, but do not disable
746 // vndk_prebuilt_shared because they might be packed into vndk APEX
747 if !module.IsVndk() {
748 module.Disable()
749 }
750 return
751 }
752
753 var snapshotMap *snapshotMap
754
755 if lib, ok := module.linker.(libraryInterface); ok {
756 if lib.static() {
757 snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
758 } else if lib.shared() {
759 snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
760 } else {
761 // header
762 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
763 }
764 } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
765 snapshotMap = vendorSnapshotBinaries(ctx.Config())
766 } else {
767 return
768 }
769
770 vendorSnapshotsLock.Lock()
771 defer vendorSnapshotsLock.Unlock()
772 snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
773}
774
775// Disables source modules which have snapshots
776func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
Inseob Kim5f64aec2020-02-18 17:27:19 +0900777 if !ctx.Device() {
778 return
779 }
780
Inseob Kimeec88e12020-01-22 11:11:29 +0900781 vndkVersion := ctx.DeviceConfig().VndkVersion()
782 // don't need snapshot if current
783 if vndkVersion == "current" || vndkVersion == "" {
784 return
785 }
786
787 module, ok := ctx.Module().(*Module)
788 if !ok {
789 return
790 }
791
Inseob Kim5f64aec2020-02-18 17:27:19 +0900792 // vendor suffix should be added to snapshots if the source module isn't vendor: true.
793 if !module.SocSpecific() {
794 // But we can't just check SocSpecific() since we already passed the image mutator.
795 // Check ramdisk and recovery to see if we are real "vendor: true" module.
796 ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk()
797 recovery_available := module.InRecovery() && !module.OnlyInRecovery()
Inseob Kimeec88e12020-01-22 11:11:29 +0900798
Inseob Kim5f64aec2020-02-18 17:27:19 +0900799 if !ramdisk_available && !recovery_available {
800 vendorSnapshotsLock.Lock()
801 defer vendorSnapshotsLock.Unlock()
802
803 vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true
804 }
Inseob Kimeec88e12020-01-22 11:11:29 +0900805 }
806
807 if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() {
808 // only non-snapshot modules with BOARD_VNDK_VERSION
809 return
810 }
811
812 var snapshotMap *snapshotMap
813
814 if lib, ok := module.linker.(libraryInterface); ok {
815 if lib.static() {
816 snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
817 } else if lib.shared() {
818 snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
819 } else {
820 // header
821 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
822 }
823 } else if _, ok := module.linker.(*binaryDecorator); ok {
824 snapshotMap = vendorSnapshotBinaries(ctx.Config())
825 } else if _, ok := module.linker.(*prebuiltBinaryLinker); ok {
826 snapshotMap = vendorSnapshotBinaries(ctx.Config())
827 } else {
828 return
829 }
830
831 if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok {
832 // Corresponding snapshot doesn't exist
833 return
834 }
835
836 // Disables source modules if corresponding snapshot exists.
837 if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() {
838 // But do not disable because the shared variant depends on the static variant.
839 module.SkipInstall()
840 module.Properties.HideFromMake = true
841 } else {
842 module.Disable()
843 }
844}