• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18	"encoding/json"
19	"errors"
20	"fmt"
21	"path/filepath"
22	"sort"
23	"strings"
24
25	"android/soong/android"
26	"android/soong/cc/config"
27	"android/soong/etc"
28
29	"github.com/google/blueprint"
30)
31
32const (
33	llndkLibrariesTxt                = "llndk.libraries.txt"
34	vndkCoreLibrariesTxt             = "vndkcore.libraries.txt"
35	vndkSpLibrariesTxt               = "vndksp.libraries.txt"
36	vndkPrivateLibrariesTxt          = "vndkprivate.libraries.txt"
37	vndkProductLibrariesTxt          = "vndkproduct.libraries.txt"
38	vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt"
39)
40
41func VndkLibrariesTxtModules(vndkVersion string) []string {
42	if vndkVersion == "current" {
43		return []string{
44			llndkLibrariesTxt,
45			vndkCoreLibrariesTxt,
46			vndkSpLibrariesTxt,
47			vndkPrivateLibrariesTxt,
48			vndkProductLibrariesTxt,
49		}
50	}
51	// Snapshot vndks have their own *.libraries.VER.txt files.
52	// Note that snapshots don't have "vndkcorevariant.libraries.VER.txt"
53	return []string{
54		insertVndkVersion(llndkLibrariesTxt, vndkVersion),
55		insertVndkVersion(vndkCoreLibrariesTxt, vndkVersion),
56		insertVndkVersion(vndkSpLibrariesTxt, vndkVersion),
57		insertVndkVersion(vndkPrivateLibrariesTxt, vndkVersion),
58		insertVndkVersion(vndkProductLibrariesTxt, vndkVersion),
59	}
60}
61
62type VndkProperties struct {
63	Vndk struct {
64		// declared as a VNDK or VNDK-SP module. The vendor variant
65		// will be installed in /system instead of /vendor partition.
66		//
67		// `vendor_available` and `product_available` must be explicitly
68		// set to either true or false together with `vndk: {enabled: true}`.
69		Enabled *bool
70
71		// declared as a VNDK-SP module, which is a subset of VNDK.
72		//
73		// `vndk: { enabled: true }` must set together.
74		//
75		// All these modules are allowed to link to VNDK-SP or LL-NDK
76		// modules only. Other dependency will cause link-type errors.
77		//
78		// If `support_system_process` is not set or set to false,
79		// the module is VNDK-core and can link to other VNDK-core,
80		// VNDK-SP or LL-NDK modules only.
81		Support_system_process *bool
82
83		// declared as a VNDK-private module.
84		// This module still creates the vendor and product variants refering
85		// to the `vendor_available: true` and `product_available: true`
86		// properties. However, it is only available to the other VNDK modules
87		// but not to the non-VNDK vendor or product modules.
88		Private *bool
89
90		// Extending another module
91		Extends *string
92	}
93}
94
95type vndkdep struct {
96	Properties VndkProperties
97}
98
99func (vndk *vndkdep) props() []interface{} {
100	return []interface{}{&vndk.Properties}
101}
102
103func (vndk *vndkdep) begin(ctx BaseModuleContext) {}
104
105func (vndk *vndkdep) deps(ctx BaseModuleContext, deps Deps) Deps {
106	return deps
107}
108
109func (vndk *vndkdep) isVndk() bool {
110	return Bool(vndk.Properties.Vndk.Enabled)
111}
112
113func (vndk *vndkdep) isVndkSp() bool {
114	return Bool(vndk.Properties.Vndk.Support_system_process)
115}
116
117func (vndk *vndkdep) isVndkExt() bool {
118	return vndk.Properties.Vndk.Extends != nil
119}
120
121func (vndk *vndkdep) getVndkExtendsModuleName() string {
122	return String(vndk.Properties.Vndk.Extends)
123}
124
125func (vndk *vndkdep) typeName() string {
126	if !vndk.isVndk() {
127		return "native:vendor"
128	}
129	if !vndk.isVndkExt() {
130		if !vndk.isVndkSp() {
131			return "native:vendor:vndk"
132		}
133		return "native:vendor:vndksp"
134	}
135	if !vndk.isVndkSp() {
136		return "native:vendor:vndkext"
137	}
138	return "native:vendor:vndkspext"
139}
140
141// VNDK link type check from a module with UseVndk() == true.
142func (vndk *vndkdep) vndkCheckLinkType(ctx android.BaseModuleContext, to *Module, tag blueprint.DependencyTag) {
143	if to.linker == nil {
144		return
145	}
146	if !vndk.isVndk() {
147		// Non-VNDK modules those installed to /vendor, /system/vendor,
148		// /product or /system/product cannot depend on VNDK-private modules
149		// that include VNDK-core-private, VNDK-SP-private and LLNDK-private.
150		if to.IsVndkPrivate() {
151			ctx.ModuleErrorf("non-VNDK module should not link to %q which has `private: true`", to.Name())
152		}
153	}
154	if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
155		// Check only shared libraries.
156		// Other (static) libraries are allowed to link.
157		return
158	}
159
160	if to.IsLlndk() {
161		// LL-NDK libraries are allowed to link
162		return
163	}
164
165	if !to.UseVndk() {
166		ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
167			vndk.typeName(), to.Name())
168		return
169	}
170	if tag == vndkExtDepTag {
171		// Ensure `extends: "name"` property refers a vndk module that has vendor_available
172		// and has identical vndk properties.
173		if to.vndkdep == nil || !to.vndkdep.isVndk() {
174			ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name())
175			return
176		}
177		if vndk.isVndkSp() != to.vndkdep.isVndkSp() {
178			ctx.ModuleErrorf(
179				"`extends` refers a module %q with mismatched support_system_process",
180				to.Name())
181			return
182		}
183		if to.IsVndkPrivate() {
184			ctx.ModuleErrorf(
185				"`extends` refers module %q which has `private: true`",
186				to.Name())
187			return
188		}
189	}
190	if to.vndkdep == nil {
191		return
192	}
193
194	// Check the dependencies of VNDK shared libraries.
195	if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil {
196		ctx.ModuleErrorf("(%s) should not link to %q (%s): %v",
197			vndk.typeName(), to.Name(), to.vndkdep.typeName(), err)
198		return
199	}
200}
201
202func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error {
203	// Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules.
204	if from.isVndkExt() {
205		if from.isVndkSp() {
206			if to.isVndk() && !to.isVndkSp() {
207				return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions")
208			}
209			return nil
210		}
211		// VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
212		return nil
213	}
214	if from.isVndk() {
215		if to.isVndkExt() {
216			return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions")
217		}
218		if from.isVndkSp() {
219			if !to.isVndkSp() {
220				return errors.New("VNDK-SP must only depend on VNDK-SP")
221			}
222			return nil
223		}
224		if !to.isVndk() {
225			return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP")
226		}
227		return nil
228	}
229	// Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
230	return nil
231}
232
233type moduleListerFunc func(ctx android.SingletonContext) (moduleNames, fileNames []string)
234
235var (
236	llndkLibraries                = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsLLNDK && !m.Header() })
237	vndkSPLibraries               = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKSP })
238	vndkCoreLibraries             = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKCore })
239	vndkPrivateLibraries          = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKPrivate })
240	vndkProductLibraries          = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKProduct })
241	vndkUsingCoreVariantLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKUsingCoreVariant })
242)
243
244// vndkModuleLister takes a predicate that operates on a Module and returns a moduleListerFunc
245// that produces a list of module names and output file names for which the predicate returns true.
246func vndkModuleLister(predicate func(*Module) bool) moduleListerFunc {
247	return func(ctx android.SingletonContext) (moduleNames, fileNames []string) {
248		ctx.VisitAllModules(func(m android.Module) {
249			if c, ok := m.(*Module); ok && predicate(c) {
250				filename, err := getVndkFileName(c)
251				if err != nil {
252					ctx.ModuleErrorf(m, "%s", err)
253				}
254				moduleNames = append(moduleNames, ctx.ModuleName(m))
255				fileNames = append(fileNames, filename)
256			}
257		})
258		moduleNames = android.SortedUniqueStrings(moduleNames)
259		fileNames = android.SortedUniqueStrings(fileNames)
260		return
261	}
262}
263
264// vndkModuleListRemover takes a moduleListerFunc and a prefix and returns a moduleListerFunc
265// that returns the same lists as the input moduleListerFunc, but with  modules with the
266// given prefix removed.
267func vndkModuleListRemover(lister moduleListerFunc, prefix string) moduleListerFunc {
268	return func(ctx android.SingletonContext) (moduleNames, fileNames []string) {
269		moduleNames, fileNames = lister(ctx)
270		filter := func(in []string) []string {
271			out := make([]string, 0, len(in))
272			for _, lib := range in {
273				if strings.HasPrefix(lib, prefix) {
274					continue
275				}
276				out = append(out, lib)
277			}
278			return out
279		}
280		return filter(moduleNames), filter(fileNames)
281	}
282}
283
284var vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey")
285
286func vndkMustUseVendorVariantList(cfg android.Config) []string {
287	return cfg.Once(vndkMustUseVendorVariantListKey, func() interface{} {
288		return config.VndkMustUseVendorVariantList
289	}).([]string)
290}
291
292// test may call this to override global configuration(config.VndkMustUseVendorVariantList)
293// when it is called, it must be before the first call to vndkMustUseVendorVariantList()
294func setVndkMustUseVendorVariantListForTest(config android.Config, mustUseVendorVariantList []string) {
295	config.Once(vndkMustUseVendorVariantListKey, func() interface{} {
296		return mustUseVendorVariantList
297	})
298}
299
300func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
301	if m.InProduct() {
302		// We may skip the steps for the product variants because they
303		// are already covered by the vendor variants.
304		return
305	}
306
307	name := m.BaseModuleName()
308
309	if lib := m.library; lib != nil && lib.hasStubsVariants() && name != "libz" {
310		// b/155456180 libz is the ONLY exception here. We don't want to make
311		// libz an LLNDK library because we in general can't guarantee that
312		// libz will behave consistently especially about the compression.
313		// i.e. the compressed output might be different across releases.
314		// As the library is an external one, it's risky to keep the compatibility
315		// promise if it becomes an LLNDK.
316		mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK")
317	}
318
319	if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
320		m.Properties.MustUseVendorVariant = true
321	}
322	if mctx.DeviceConfig().VndkUseCoreVariant() && !m.Properties.MustUseVendorVariant {
323		m.VendorProperties.IsVNDKUsingCoreVariant = true
324	}
325
326	if m.vndkdep.isVndkSp() {
327		m.VendorProperties.IsVNDKSP = true
328	} else {
329		m.VendorProperties.IsVNDKCore = true
330	}
331	if m.IsVndkPrivate() {
332		m.VendorProperties.IsVNDKPrivate = true
333	}
334	if Bool(m.VendorProperties.Product_available) {
335		m.VendorProperties.IsVNDKProduct = true
336	}
337}
338
339// Check for modules that mustn't be VNDK
340func shouldSkipVndkMutator(m *Module) bool {
341	if !m.Enabled() {
342		return true
343	}
344	if !m.Device() {
345		// Skip non-device modules
346		return true
347	}
348	if m.Target().NativeBridge == android.NativeBridgeEnabled {
349		// Skip native_bridge modules
350		return true
351	}
352	return false
353}
354
355func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool {
356	if shouldSkipVndkMutator(m) {
357		return false
358	}
359
360	// prebuilt vndk modules should match with device
361	// TODO(b/142675459): Use enabled: to select target device in vndk_prebuilt_shared
362	// When b/142675459 is landed, remove following check
363	if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok && !p.matchesWithDevice(mctx.DeviceConfig()) {
364		return false
365	}
366
367	if lib, ok := m.linker.(libraryInterface); ok {
368		// VNDK APEX for VNDK-Lite devices will have VNDK-SP libraries from core variants
369		if mctx.DeviceConfig().VndkVersion() == "" {
370			// b/73296261: filter out libz.so because it is considered as LLNDK for VNDK-lite devices
371			if mctx.ModuleName() == "libz" {
372				return false
373			}
374			return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.IsVndkSp()
375		}
376
377		useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
378			mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
379		return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant
380	}
381	return false
382}
383
384// gather list of vndk-core, vndk-sp, and ll-ndk libs
385func VndkMutator(mctx android.BottomUpMutatorContext) {
386	m, ok := mctx.Module().(*Module)
387	if !ok {
388		return
389	}
390
391	if shouldSkipVndkMutator(m) {
392		return
393	}
394
395	lib, isLib := m.linker.(*libraryDecorator)
396	prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)
397
398	if m.UseVndk() && isLib && lib.hasLLNDKStubs() {
399		m.VendorProperties.IsLLNDK = true
400		m.VendorProperties.IsVNDKPrivate = Bool(lib.Properties.Llndk.Private)
401	}
402	if m.UseVndk() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
403		m.VendorProperties.IsLLNDK = true
404		m.VendorProperties.IsVNDKPrivate = Bool(prebuiltLib.Properties.Llndk.Private)
405	}
406
407	if (isLib && lib.buildShared()) || (isPrebuiltLib && prebuiltLib.buildShared()) {
408		if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
409			processVndkLibrary(mctx, m)
410			return
411		}
412	}
413}
414
415func init() {
416	RegisterVndkLibraryTxtTypes(android.InitRegistrationContext)
417	android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
418}
419
420func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) {
421	ctx.RegisterSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory)
422	ctx.RegisterSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory)
423	ctx.RegisterSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory)
424	ctx.RegisterSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory)
425	ctx.RegisterSingletonModuleType("vndkproduct_libraries_txt", vndkProductLibrariesTxtFactory)
426	ctx.RegisterSingletonModuleType("vndkcorevariant_libraries_txt", vndkUsingCoreVariantLibrariesTxtFactory)
427}
428
429type vndkLibrariesTxt struct {
430	android.SingletonModuleBase
431
432	lister               moduleListerFunc
433	makeVarName          string
434	filterOutFromMakeVar string
435
436	properties VndkLibrariesTxtProperties
437
438	outputFile  android.OutputPath
439	moduleNames []string
440	fileNames   []string
441}
442
443type VndkLibrariesTxtProperties struct {
444	Insert_vndk_version *bool
445}
446
447var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
448var _ android.OutputFileProducer = &vndkLibrariesTxt{}
449
450// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries
451// generated by Soong but can be referenced by other modules.
452// For example, apex_vndk can depend on these files as prebuilt.
453// Make uses LLNDK_LIBRARIES to determine which libraries to install.
454// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
455// Therefore, by removing the library here, we cause it to only be installed if libc
456// depends on it.
457func llndkLibrariesTxtFactory() android.SingletonModule {
458	return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan-")
459}
460
461// vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries
462// generated by Soong but can be referenced by other modules.
463// For example, apex_vndk can depend on these files as prebuilt.
464func vndkSPLibrariesTxtFactory() android.SingletonModule {
465	return newVndkLibrariesTxt(vndkSPLibraries, "VNDK_SAMEPROCESS_LIBRARIES")
466}
467
468// vndkcore_libraries_txt is a singleton module whose content is a list of VNDK core libraries
469// generated by Soong but can be referenced by other modules.
470// For example, apex_vndk can depend on these files as prebuilt.
471func vndkCoreLibrariesTxtFactory() android.SingletonModule {
472	return newVndkLibrariesTxt(vndkCoreLibraries, "VNDK_CORE_LIBRARIES")
473}
474
475// vndkprivate_libraries_txt is a singleton module whose content is a list of VNDK private libraries
476// generated by Soong but can be referenced by other modules.
477// For example, apex_vndk can depend on these files as prebuilt.
478func vndkPrivateLibrariesTxtFactory() android.SingletonModule {
479	return newVndkLibrariesTxt(vndkPrivateLibraries, "VNDK_PRIVATE_LIBRARIES")
480}
481
482// vndkproduct_libraries_txt is a singleton module whose content is a list of VNDK product libraries
483// generated by Soong but can be referenced by other modules.
484// For example, apex_vndk can depend on these files as prebuilt.
485func vndkProductLibrariesTxtFactory() android.SingletonModule {
486	return newVndkLibrariesTxt(vndkProductLibraries, "VNDK_PRODUCT_LIBRARIES")
487}
488
489// vndkcorevariant_libraries_txt is a singleton module whose content is a list of VNDK libraries
490// that are using the core variant, generated by Soong but can be referenced by other modules.
491// For example, apex_vndk can depend on these files as prebuilt.
492func vndkUsingCoreVariantLibrariesTxtFactory() android.SingletonModule {
493	return newVndkLibrariesTxt(vndkUsingCoreVariantLibraries, "VNDK_USING_CORE_VARIANT_LIBRARIES")
494}
495
496func newVndkLibrariesWithMakeVarFilter(lister moduleListerFunc, makeVarName string, filter string) android.SingletonModule {
497	m := &vndkLibrariesTxt{
498		lister:               lister,
499		makeVarName:          makeVarName,
500		filterOutFromMakeVar: filter,
501	}
502	m.AddProperties(&m.properties)
503	android.InitAndroidModule(m)
504	return m
505}
506
507func newVndkLibrariesTxt(lister moduleListerFunc, makeVarName string) android.SingletonModule {
508	return newVndkLibrariesWithMakeVarFilter(lister, makeVarName, "")
509}
510
511func insertVndkVersion(filename string, vndkVersion string) string {
512	if index := strings.LastIndex(filename, "."); index != -1 {
513		return filename[:index] + "." + vndkVersion + filename[index:]
514	}
515	return filename
516}
517
518func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
519	var filename string
520	if BoolDefault(txt.properties.Insert_vndk_version, true) {
521		filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
522	} else {
523		filename = txt.Name()
524	}
525
526	txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
527
528	installPath := android.PathForModuleInstall(ctx, "etc")
529	ctx.InstallFile(installPath, filename, txt.outputFile)
530}
531
532func (txt *vndkLibrariesTxt) GenerateSingletonBuildActions(ctx android.SingletonContext) {
533	txt.moduleNames, txt.fileNames = txt.lister(ctx)
534	android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n"))
535}
536
537func (txt *vndkLibrariesTxt) AndroidMkEntries() []android.AndroidMkEntries {
538	return []android.AndroidMkEntries{android.AndroidMkEntries{
539		Class:      "ETC",
540		OutputFile: android.OptionalPathForPath(txt.outputFile),
541		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
542			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
543				entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base())
544			},
545		},
546	}}
547}
548
549func (txt *vndkLibrariesTxt) MakeVars(ctx android.MakeVarsContext) {
550	filter := func(modules []string, prefix string) []string {
551		if prefix == "" {
552			return modules
553		}
554		var result []string
555		for _, module := range modules {
556			if strings.HasPrefix(module, prefix) {
557				continue
558			} else {
559				result = append(result, module)
560			}
561		}
562		return result
563	}
564	ctx.Strict(txt.makeVarName, strings.Join(filter(txt.moduleNames, txt.filterOutFromMakeVar), " "))
565}
566
567// PrebuiltEtcModule interface
568func (txt *vndkLibrariesTxt) OutputFile() android.OutputPath {
569	return txt.outputFile
570}
571
572// PrebuiltEtcModule interface
573func (txt *vndkLibrariesTxt) BaseDir() string {
574	return "etc"
575}
576
577// PrebuiltEtcModule interface
578func (txt *vndkLibrariesTxt) SubDir() string {
579	return ""
580}
581
582func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) {
583	return android.Paths{txt.outputFile}, nil
584}
585
586func VndkSnapshotSingleton() android.Singleton {
587	return &vndkSnapshotSingleton{}
588}
589
590type vndkSnapshotSingleton struct {
591	vndkLibrariesFile   android.OutputPath
592	vndkSnapshotZipFile android.OptionalPath
593}
594
595func isVndkSnapshotAware(config android.DeviceConfig, m LinkableInterface,
596	apexInfo android.ApexInfo) (vndkType string, isVndkSnapshotLib bool) {
597
598	if m.Target().NativeBridge == android.NativeBridgeEnabled {
599		return "", false
600	}
601	// !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants.
602	// !installable: Snapshot only cares about "installable" modules.
603	// !m.IsLlndk: llndk stubs are required for building against snapshots.
604	// IsSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense.
605	// !outputFile.Valid: Snapshot requires valid output file.
606	if !m.InVendor() || (!installable(m, apexInfo) && !m.IsLlndk()) || m.IsSnapshotPrebuilt() || !m.OutputFile().Valid() {
607		return "", false
608	}
609	if !m.IsSnapshotLibrary() || !m.Shared() {
610		return "", false
611	}
612	if m.VndkVersion() == config.PlatformVndkVersion() {
613		if m.IsVndk() && !m.IsVndkExt() {
614			if m.IsVndkSp() {
615				return "vndk-sp", true
616			} else {
617				return "vndk-core", true
618			}
619		} else if m.HasLlndkStubs() && m.StubsVersion() == "" {
620			// Use default version for the snapshot.
621			return "llndk-stub", true
622		}
623	}
624
625	return "", false
626}
627
628func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
629	// build these files even if PlatformVndkVersion or BoardVndkVersion is not set
630	c.buildVndkLibrariesTxtFiles(ctx)
631
632	// BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
633	if ctx.DeviceConfig().VndkVersion() != "current" {
634		return
635	}
636
637	if ctx.DeviceConfig().PlatformVndkVersion() == "" {
638		return
639	}
640
641	var snapshotOutputs android.Paths
642
643	/*
644		VNDK snapshot zipped artifacts directory structure:
645		{SNAPSHOT_ARCH}/
646			arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
647				shared/
648					vndk-core/
649						(VNDK-core libraries, e.g. libbinder.so)
650					vndk-sp/
651						(VNDK-SP libraries, e.g. libc++.so)
652					llndk-stub/
653						(LLNDK stub libraries)
654			arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
655				shared/
656					vndk-core/
657						(VNDK-core libraries, e.g. libbinder.so)
658					vndk-sp/
659						(VNDK-SP libraries, e.g. libc++.so)
660					llndk-stub/
661						(LLNDK stub libraries)
662			binder32/
663				(This directory is newly introduced in v28 (Android P) to hold
664				prebuilts built for 32-bit binder interface.)
665				arch-{TARGET_ARCH}-{TARGE_ARCH_VARIANT}/
666					...
667			configs/
668				(various *.txt configuration files)
669			include/
670				(header files of same directory structure with source tree)
671			NOTICE_FILES/
672				(notice files of libraries, e.g. libcutils.so.txt)
673	*/
674
675	snapshotDir := "vndk-snapshot"
676	snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
677
678	configsDir := filepath.Join(snapshotArchDir, "configs")
679	noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
680	includeDir := filepath.Join(snapshotArchDir, "include")
681
682	// set of notice files copied.
683	noticeBuilt := make(map[string]bool)
684
685	// paths of VNDK modules for GPL license checking
686	modulePaths := make(map[string]string)
687
688	// actual module names of .so files
689	// e.g. moduleNames["libprotobuf-cpp-full-3.9.1.so"] = "libprotobuf-cpp-full"
690	moduleNames := make(map[string]string)
691
692	var headers android.Paths
693
694	// installVndkSnapshotLib copies built .so file from the module.
695	// Also, if the build artifacts is on, write a json file which contains all exported flags
696	// with FlagExporterInfo.
697	installVndkSnapshotLib := func(m *Module, vndkType string) (android.Paths, bool) {
698		var ret android.Paths
699
700		targetArch := "arch-" + m.Target().Arch.ArchType.String()
701		if m.Target().Arch.ArchVariant != "" {
702			targetArch += "-" + m.Target().Arch.ArchVariant
703		}
704
705		libPath := m.outputFile.Path()
706		snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
707		ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut))
708
709		if ctx.Config().VndkSnapshotBuildArtifacts() {
710			prop := struct {
711				ExportedDirs        []string `json:",omitempty"`
712				ExportedSystemDirs  []string `json:",omitempty"`
713				ExportedFlags       []string `json:",omitempty"`
714				RelativeInstallPath string   `json:",omitempty"`
715			}{}
716			exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
717			prop.ExportedFlags = exportedInfo.Flags
718			prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
719			prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
720			prop.RelativeInstallPath = m.RelativeInstallPath()
721
722			propOut := snapshotLibOut + ".json"
723
724			j, err := json.Marshal(prop)
725			if err != nil {
726				ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
727				return nil, false
728			}
729			ret = append(ret, writeStringToFileRule(ctx, string(j), propOut))
730		}
731		return ret, true
732	}
733
734	ctx.VisitAllModules(func(module android.Module) {
735		m, ok := module.(*Module)
736		if !ok || !m.Enabled() {
737			return
738		}
739
740		apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
741
742		vndkType, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo)
743		if !ok {
744			return
745		}
746
747		// For all snapshot candidates, the followings are captured.
748		//   - .so files
749		//   - notice files
750		//
751		// The followings are also captured if VNDK_SNAPSHOT_BUILD_ARTIFACTS.
752		//   - .json files containing exported flags
753		//   - exported headers from collectHeadersForSnapshot()
754		//
755		// Headers are deduplicated after visiting all modules.
756
757		// install .so files for appropriate modules.
758		// Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS
759		libs, ok := installVndkSnapshotLib(m, vndkType)
760		if !ok {
761			return
762		}
763		snapshotOutputs = append(snapshotOutputs, libs...)
764
765		// These are for generating module_names.txt and module_paths.txt
766		stem := m.outputFile.Path().Base()
767		moduleNames[stem] = ctx.ModuleName(m)
768		modulePaths[stem] = ctx.ModuleDir(m)
769
770		if len(m.NoticeFiles()) > 0 {
771			noticeName := stem + ".txt"
772			// skip already copied notice file
773			if _, ok := noticeBuilt[noticeName]; !ok {
774				noticeBuilt[noticeName] = true
775				snapshotOutputs = append(snapshotOutputs, combineNoticesRule(
776					ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName)))
777			}
778		}
779
780		if ctx.Config().VndkSnapshotBuildArtifacts() {
781			headers = append(headers, m.SnapshotHeaders()...)
782		}
783	})
784
785	// install all headers after removing duplicates
786	for _, header := range android.FirstUniquePaths(headers) {
787		snapshotOutputs = append(snapshotOutputs, copyFileRule(
788			ctx, header, filepath.Join(includeDir, header.String())))
789	}
790
791	// install *.libraries.txt except vndkcorevariant.libraries.txt
792	ctx.VisitAllModules(func(module android.Module) {
793		m, ok := module.(*vndkLibrariesTxt)
794		if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt {
795			return
796		}
797		snapshotOutputs = append(snapshotOutputs, copyFileRule(
798			ctx, m.OutputFile(), filepath.Join(configsDir, m.Name())))
799	})
800
801	/*
802		module_paths.txt contains paths on which VNDK modules are defined.
803		e.g.,
804			libbase.so system/libbase
805			libc.so bionic/libc
806			...
807	*/
808	snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, modulePaths, filepath.Join(configsDir, "module_paths.txt")))
809
810	/*
811		module_names.txt contains names as which VNDK modules are defined,
812		because output filename and module name can be different with stem and suffix properties.
813
814		e.g.,
815			libcutils.so libcutils
816			libprotobuf-cpp-full-3.9.2.so libprotobuf-cpp-full
817			...
818	*/
819	snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, moduleNames, filepath.Join(configsDir, "module_names.txt")))
820
821	// All artifacts are ready. Sort them to normalize ninja and then zip.
822	sort.Slice(snapshotOutputs, func(i, j int) bool {
823		return snapshotOutputs[i].String() < snapshotOutputs[j].String()
824	})
825
826	zipPath := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+".zip")
827	zipRule := android.NewRuleBuilder(pctx, ctx)
828
829	// filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
830	snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+"_list")
831	rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp")
832	zipRule.Command().
833		Text("tr").
834		FlagWithArg("-d ", "\\'").
835		FlagWithRspFileInputList("< ", rspFile, snapshotOutputs).
836		FlagWithOutput("> ", snapshotOutputList)
837
838	zipRule.Temporary(snapshotOutputList)
839
840	zipRule.Command().
841		BuiltTool("soong_zip").
842		FlagWithOutput("-o ", zipPath).
843		FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
844		FlagWithInput("-l ", snapshotOutputList)
845
846	zipRule.Build(zipPath.String(), "vndk snapshot "+zipPath.String())
847	zipRule.DeleteTemporaryFiles()
848	c.vndkSnapshotZipFile = android.OptionalPathForPath(zipPath)
849}
850
851func getVndkFileName(m *Module) (string, error) {
852	if library, ok := m.linker.(*libraryDecorator); ok {
853		return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
854	}
855	if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok {
856		return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
857	}
858	return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker)
859}
860
861func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
862	// Build list of vndk libs as merged & tagged & filter-out(libclang_rt):
863	// Since each target have different set of libclang_rt.* files,
864	// keep the common set of files in vndk.libraries.txt
865	_, llndk := vndkModuleListRemover(llndkLibraries, "libclang_rt.")(ctx)
866	_, vndkcore := vndkModuleListRemover(vndkCoreLibraries, "libclang_rt.")(ctx)
867	_, vndksp := vndkSPLibraries(ctx)
868	_, vndkprivate := vndkPrivateLibraries(ctx)
869	_, vndkproduct := vndkModuleListRemover(vndkProductLibraries, "libclang_rt.")(ctx)
870	var merged []string
871	merged = append(merged, addPrefix(llndk, "LLNDK: ")...)
872	merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
873	merged = append(merged, addPrefix(vndkcore, "VNDK-core: ")...)
874	merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
875	merged = append(merged, addPrefix(vndkproduct, "VNDK-product: ")...)
876	c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
877	android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
878}
879
880func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
881	// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
882	// they been moved to an apex.
883	movedToApexLlndkLibraries := make(map[string]bool)
884	ctx.VisitAllModules(func(module android.Module) {
885		if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() {
886			// Skip bionic libs, they are handled in different manner
887			name := library.implementationModuleName(module.(*Module).BaseModuleName())
888			if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) {
889				movedToApexLlndkLibraries[name] = true
890			}
891		}
892	})
893
894	ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES",
895		strings.Join(android.SortedStringKeys(movedToApexLlndkLibraries), " "))
896
897	ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String())
898	ctx.Strict("SOONG_VNDK_SNAPSHOT_ZIP", c.vndkSnapshotZipFile.String())
899}
900