• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 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	"fmt"
19	"io"
20	"path/filepath"
21	"regexp"
22	"slices"
23	"strconv"
24	"strings"
25	"sync"
26
27	"android/soong/android"
28	"android/soong/cc/config"
29
30	"github.com/google/blueprint"
31	"github.com/google/blueprint/depset"
32	"github.com/google/blueprint/pathtools"
33	"github.com/google/blueprint/proptools"
34)
35
36// LibraryProperties is a collection of properties shared by cc library rules/cc.
37type LibraryProperties struct {
38	// local file name to pass to the linker as -exported_symbols_list
39	Exported_symbols_list *string `android:"path,arch_variant"`
40	// local file name to pass to the linker as -unexported_symbols_list
41	Unexported_symbols_list *string `android:"path,arch_variant"`
42	// local file name to pass to the linker as -force_symbols_not_weak_list
43	Force_symbols_not_weak_list *string `android:"path,arch_variant"`
44	// local file name to pass to the linker as -force_symbols_weak_list
45	Force_symbols_weak_list *string `android:"path,arch_variant"`
46
47	// rename host libraries to prevent overlap with system installed libraries
48	Unique_host_soname *bool
49
50	Aidl struct {
51		// export headers generated from .aidl sources
52		Export_aidl_headers *bool
53	}
54
55	Proto struct {
56		// export headers generated from .proto sources
57		Export_proto_headers *bool
58	}
59
60	Sysprop struct {
61		// Whether platform owns this sysprop library.
62		Platform *bool
63	} `blueprint:"mutated"`
64
65	Static_ndk_lib *bool
66
67	// Generate stubs to make this library accessible to APEXes.
68	Stubs StubsProperties `android:"arch_variant"`
69
70	// set the name of the output
71	Stem *string `android:"arch_variant"`
72
73	// set suffix of the name of the output
74	Suffix *string `android:"arch_variant"`
75
76	// Properties for ABI compatibility checker.
77	Header_abi_checker headerAbiCheckerProperties
78
79	Target struct {
80		Vendor, Product struct {
81			// set suffix of the name of the output
82			Suffix *string `android:"arch_variant"`
83
84			Header_abi_checker headerAbiCheckerProperties
85
86			// Disable stubs for vendor/product variants
87			// This is a workaround to keep `stubs` only for "core" variant (not product/vendor).
88			// It would be nice if we could put `stubs` into a `target: { core: {} }`
89			// block but it's not supported in soong yet. This could be removed/simplified once we have
90			// a better syntax.
91			No_stubs bool
92		}
93
94		Platform struct {
95			Header_abi_checker headerAbiCheckerProperties
96		}
97	}
98
99	// Names of modules to be overridden. Listed modules can only be other shared libraries
100	// (in Make or Soong).
101	// This does not completely prevent installation of the overridden libraries, but if both
102	// binaries would be installed by default (in PRODUCT_PACKAGES) the other library will be removed
103	// from PRODUCT_PACKAGES.
104	Overrides []string
105
106	// Inject boringssl hash into the shared library.  This is only intended for use by external/boringssl.
107	Inject_bssl_hash *bool `android:"arch_variant"`
108
109	// If this is an LLNDK library, properties to describe the LLNDK stubs.  Will be copied from
110	// the module pointed to by llndk_stubs if it is set.
111	Llndk llndkLibraryProperties `android:"arch_variant"`
112
113	// If this is a vendor public library, properties to describe the vendor public library stubs.
114	Vendor_public_library vendorPublicLibraryProperties
115}
116
117type StubsProperties struct {
118	// Relative path to the symbol map. The symbol map provides the list of
119	// symbols that are exported for stubs variant of this library.
120	Symbol_file *string `android:"path,arch_variant"`
121
122	// List versions to generate stubs libs for. The version name "current" is always
123	// implicitly added.
124	Versions []string
125
126	// Whether to not require the implementation of the library to be installed if a
127	// client of the stubs is installed. Defaults to true; set to false if the
128	// implementation is made available by some other means, e.g. in a Microdroid
129	// virtual machine.
130	Implementation_installable *bool
131}
132
133// StaticProperties is a properties stanza to affect only attributes of the "static" variants of a
134// library module.
135type StaticProperties struct {
136	Static StaticOrSharedProperties `android:"arch_variant"`
137}
138
139// SharedProperties is a properties stanza to affect only attributes of the "shared" variants of a
140// library module.
141type SharedProperties struct {
142	Shared StaticOrSharedProperties `android:"arch_variant"`
143}
144
145// StaticOrSharedProperties is an embedded struct representing properties to affect attributes of
146// either only the "static" variants or only the "shared" variants of a library module. These override
147// the base properties of the same name.
148// Use `StaticProperties` or `SharedProperties`, depending on which variant is needed.
149// `StaticOrSharedProperties` exists only to avoid duplication.
150type StaticOrSharedProperties struct {
151	Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
152
153	Tidy_disabled_srcs []string `android:"path,arch_variant"`
154
155	Tidy_timeout_srcs []string `android:"path,arch_variant"`
156
157	Sanitized Sanitized `android:"arch_variant"`
158
159	Cflags proptools.Configurable[[]string] `android:"arch_variant"`
160
161	Enabled            *bool                            `android:"arch_variant"`
162	Whole_static_libs  proptools.Configurable[[]string] `android:"arch_variant"`
163	Static_libs        proptools.Configurable[[]string] `android:"arch_variant"`
164	Shared_libs        proptools.Configurable[[]string] `android:"arch_variant"`
165	System_shared_libs []string                         `android:"arch_variant"`
166
167	Export_shared_lib_headers []string `android:"arch_variant"`
168	Export_static_lib_headers []string `android:"arch_variant"`
169
170	Apex_available []string `android:"arch_variant"`
171
172	Installable *bool `android:"arch_variant"`
173}
174
175type LibraryMutatedProperties struct {
176	// Build a static variant
177	BuildStatic bool `blueprint:"mutated"`
178	// Build a shared variant
179	BuildShared bool `blueprint:"mutated"`
180	// This variant is shared
181	VariantIsShared bool `blueprint:"mutated"`
182	// This variant is static
183	VariantIsStatic bool `blueprint:"mutated"`
184
185	// This variant is a stubs lib
186	BuildStubs bool `blueprint:"mutated"`
187	// This variant is the latest version
188	IsLatestVersion bool `blueprint:"mutated"`
189	// Version of the stubs lib
190	StubsVersion string `blueprint:"mutated"`
191	// List of all stubs versions associated with an implementation lib
192	AllStubsVersions []string `blueprint:"mutated"`
193}
194
195type FlagExporterProperties struct {
196	// list of directories relative to the Blueprints file that will
197	// be added to the include path (using -I) for this module and any module that links
198	// against this module.  Directories listed in export_include_dirs do not need to be
199	// listed in local_include_dirs.
200	Export_include_dirs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
201
202	// list of directories that will be added to the system include path
203	// using -isystem for this module and any module that links against this module.
204	Export_system_include_dirs []string `android:"arch_variant,variant_prepend"`
205
206	Target struct {
207		Vendor, Product struct {
208			// list of exported include directories, like
209			// export_include_dirs, that will be applied to
210			// vendor or product variant of this library.
211			// This will overwrite any other declarations.
212			Override_export_include_dirs []string
213		}
214	}
215}
216
217func init() {
218	RegisterLibraryBuildComponents(android.InitRegistrationContext)
219}
220
221func RegisterLibraryBuildComponents(ctx android.RegistrationContext) {
222	ctx.RegisterModuleType("cc_library_static", LibraryStaticFactory)
223	ctx.RegisterModuleType("cc_rustlibs_for_make", LibraryMakeRustlibsFactory)
224	ctx.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
225	ctx.RegisterModuleType("cc_library", LibraryFactory)
226	ctx.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory)
227	ctx.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory)
228}
229
230// cc_library creates both static and/or shared libraries for a device and/or
231// host. By default, a cc_library has a single variant that targets the device.
232// Specifying `host_supported: true` also creates a library that targets the
233// host.
234func LibraryFactory() android.Module {
235	module, _ := NewLibrary(android.HostAndDeviceSupported)
236	// Can be used as both a static and a shared library.
237	module.sdkMemberTypes = []android.SdkMemberType{
238		sharedLibrarySdkMemberType,
239		staticLibrarySdkMemberType,
240		staticAndSharedLibrarySdkMemberType,
241	}
242	return module.Init()
243}
244
245// cc_library_static creates a static library for a device and/or host binary.
246func LibraryStaticFactory() android.Module {
247	module, library := NewLibrary(android.HostAndDeviceSupported)
248	library.BuildOnlyStatic()
249	module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
250	return module.Init()
251}
252
253// cc_rustlibs_for_make creates a static library which bundles together rust_ffi_static
254// deps for Make. This should not be depended on in Soong, and is probably not the
255// module you need unless you are sure of what you're doing. These should only
256// be declared as dependencies in Make. To ensure inclusion, rust_ffi_static modules
257// should be declared in the whole_static_libs property.
258func LibraryMakeRustlibsFactory() android.Module {
259	module, library := NewLibrary(android.HostAndDeviceSupported)
260	library.BuildOnlyStatic()
261	library.wideStaticlibForMake = true
262	module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
263	return module.Init()
264}
265
266// cc_library_shared creates a shared library for a device and/or host.
267func LibrarySharedFactory() android.Module {
268	module, library := NewLibrary(android.HostAndDeviceSupported)
269	library.BuildOnlyShared()
270	module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
271	return module.Init()
272}
273
274// cc_library_host_static creates a static library that is linkable to a host
275// binary.
276func LibraryHostStaticFactory() android.Module {
277	module, library := NewLibrary(android.HostSupported)
278	library.BuildOnlyStatic()
279	module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
280	return module.Init()
281}
282
283// cc_library_host_shared creates a shared library that is usable on a host.
284func LibraryHostSharedFactory() android.Module {
285	module, library := NewLibrary(android.HostSupported)
286	library.BuildOnlyShared()
287	module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
288	return module.Init()
289}
290
291// flagExporter is a separated portion of libraryDecorator pertaining to exported
292// include paths and flags. Keeping this dependency-related information separate
293// from the rest of library information is helpful in keeping data more structured
294// and explicit.
295type flagExporter struct {
296	Properties FlagExporterProperties
297
298	dirs         android.Paths // Include directories to be included with -I
299	systemDirs   android.Paths // System include directories to be included with -isystem
300	flags        []string      // Exported raw flags.
301	deps         android.Paths
302	headers      android.Paths
303	rustRlibDeps []RustRlibDep
304}
305
306// exportedIncludes returns the effective include paths for this module and
307// any module that links against this module. This is obtained from
308// the export_include_dirs property in the appropriate target stanza.
309func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
310	if ctx.inVendor() && f.Properties.Target.Vendor.Override_export_include_dirs != nil {
311		return android.PathsForModuleSrc(ctx, f.Properties.Target.Vendor.Override_export_include_dirs)
312	}
313	if ctx.inProduct() && f.Properties.Target.Product.Override_export_include_dirs != nil {
314		return android.PathsForModuleSrc(ctx, f.Properties.Target.Product.Override_export_include_dirs)
315	}
316	return android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs.GetOrDefault(ctx, nil))
317}
318
319func (f *flagExporter) exportedSystemIncludes(ctx ModuleContext) android.Paths {
320	return android.PathsForModuleSrc(ctx, f.Properties.Export_system_include_dirs)
321}
322
323// exportIncludes registers the include directories and system include directories to be exported
324// transitively to modules depending on this module.
325func (f *flagExporter) exportIncludes(ctx ModuleContext) {
326	f.dirs = append(f.dirs, f.exportedIncludes(ctx)...)
327	f.systemDirs = append(f.systemDirs, android.PathsForModuleSrc(ctx, f.Properties.Export_system_include_dirs)...)
328}
329
330// exportIncludesAsSystem registers the include directories and system include directories to be
331// exported transitively both as system include directories to modules depending on this module.
332func (f *flagExporter) exportIncludesAsSystem(ctx ModuleContext) {
333	// all dirs are force exported as system
334	f.systemDirs = append(f.systemDirs, f.exportedIncludes(ctx)...)
335	f.systemDirs = append(f.systemDirs, android.PathsForModuleSrc(ctx, f.Properties.Export_system_include_dirs)...)
336}
337
338// reexportDirs registers the given directories as include directories to be exported transitively
339// to modules depending on this module.
340func (f *flagExporter) reexportDirs(dirs ...android.Path) {
341	f.dirs = append(f.dirs, dirs...)
342}
343
344// reexportSystemDirs registers the given directories as system include directories
345// to be exported transitively to modules depending on this module.
346func (f *flagExporter) reexportSystemDirs(dirs ...android.Path) {
347	f.systemDirs = append(f.systemDirs, dirs...)
348}
349
350// reexportFlags registers the flags to be exported transitively to modules depending on this
351// module.
352func (f *flagExporter) reexportFlags(flags ...string) {
353	if android.PrefixInList(flags, "-I") || android.PrefixInList(flags, "-isystem") {
354		panic(fmt.Errorf("Exporting invalid flag %q: "+
355			"use reexportDirs or reexportSystemDirs to export directories", flag))
356	}
357	f.flags = append(f.flags, flags...)
358}
359
360func (f *flagExporter) reexportDeps(deps ...android.Path) {
361	f.deps = append(f.deps, deps...)
362}
363
364func (f *flagExporter) reexportRustStaticDeps(deps ...RustRlibDep) {
365	f.rustRlibDeps = append(f.rustRlibDeps, deps...)
366}
367
368// addExportedGeneratedHeaders does nothing but collects generated header files.
369// This can be differ to exportedDeps which may contain phony files to minimize ninja.
370func (f *flagExporter) addExportedGeneratedHeaders(headers ...android.Path) {
371	f.headers = append(f.headers, headers...)
372}
373
374func (f *flagExporter) setProvider(ctx android.ModuleContext) {
375	android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{
376		// Comes from Export_include_dirs property, and those of exported transitive deps
377		IncludeDirs: android.FirstUniquePaths(f.dirs),
378		// Comes from Export_system_include_dirs property, and those of exported transitive deps
379		SystemIncludeDirs: android.FirstUniquePaths(f.systemDirs),
380		// Used in very few places as a one-off way of adding extra defines.
381		Flags: f.flags,
382		// Used sparingly, for extra files that need to be explicitly exported to dependers,
383		// or for phony files to minimize ninja.
384		Deps: f.deps,
385		// Used for exporting rlib deps of static libraries to dependents.
386		RustRlibDeps: f.rustRlibDeps,
387		// For exported generated headers, such as exported aidl headers, proto headers, or
388		// sysprop headers.
389		GeneratedHeaders: f.headers,
390	})
391}
392
393// libraryDecorator wraps baseCompiler, baseLinker and baseInstaller to provide library-specific
394// functionality: static vs. shared linkage, reusing object files for shared libraries
395type libraryDecorator struct {
396	Properties        LibraryProperties
397	StaticProperties  StaticProperties
398	SharedProperties  SharedProperties
399	MutatedProperties LibraryMutatedProperties
400
401	// For reusing static library objects for shared library
402	reuseObjects Objects
403
404	// table-of-contents file to optimize out relinking when possible
405	tocFile android.OptionalPath
406
407	flagExporter
408	flagExporterInfo *FlagExporterInfo
409	stripper         Stripper
410
411	// For whole_static_libs
412	objects                      Objects
413	wholeStaticLibsFromPrebuilts android.Paths
414
415	// Uses the module's name if empty, but can be overridden. Does not include
416	// shlib suffix.
417	libName string
418
419	sabi *sabi
420
421	// Output archive of gcno coverage information files
422	coverageOutputFile android.OptionalPath
423
424	// Source Abi Diff
425	sAbiDiff android.Paths
426
427	// Location of the static library in the sysroot. Empty if the library is
428	// not included in the NDK.
429	ndkSysrootPath android.Path
430
431	// Location of the linked, unstripped library for shared libraries
432	unstrippedOutputFile android.Path
433	// Location of the linked, stripped library for shared libraries, strip: "all"
434	strippedAllOutputFile android.Path
435
436	// Location of the file that should be copied to dist dir when no explicit tag is requested
437	defaultDistFile android.Path
438
439	versionScriptPath android.OptionalPath
440
441	postInstallCmds []string
442
443	skipAPIDefine bool
444
445	// Decorated interfaces
446	*baseCompiler
447	*baseLinker
448	*baseInstaller
449
450	apiListCoverageXmlPath android.ModuleOutPath
451
452	// Path to the file containing the APIs exported by this library
453	stubsSymbolFilePath android.Path
454
455	// Forces production of the generated Rust staticlib for cc_library_static.
456	// Intended to be used to provide these generated staticlibs for Make.
457	wideStaticlibForMake bool
458}
459
460// linkerProps returns the list of properties structs relevant for this library. (For example, if
461// the library is cc_shared_library, then static-library properties are omitted.)
462func (library *libraryDecorator) linkerProps() []interface{} {
463	var props []interface{}
464	props = append(props, library.baseLinker.linkerProps()...)
465	props = append(props,
466		&library.Properties,
467		&library.MutatedProperties,
468		&library.flagExporter.Properties,
469		&library.stripper.StripProperties)
470
471	if library.MutatedProperties.BuildShared {
472		props = append(props, &library.SharedProperties)
473	}
474	if library.MutatedProperties.BuildStatic {
475		props = append(props, &library.StaticProperties)
476	}
477
478	return props
479}
480
481func CommonLibraryLinkerFlags(ctx android.ModuleContext, flags Flags,
482	toolchain config.Toolchain, libName string) Flags {
483
484	mod, ok := ctx.Module().(LinkableInterface)
485
486	if !ok {
487		ctx.ModuleErrorf("trying to add linker flags to a non-LinkableInterface module.")
488		return flags
489	}
490
491	// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
492	// all code is position independent, and then those warnings get promoted to
493	// errors.
494	if !ctx.Windows() {
495		flags.Global.CFlags = append(flags.Global.CFlags, "-fPIC")
496	}
497	if mod.Shared() {
498		var f []string
499		if toolchain.Bionic() {
500			f = append(f,
501				"-nostdlib",
502				"-Wl,--gc-sections",
503			)
504		}
505		if ctx.Darwin() {
506			f = append(f,
507				"-dynamiclib",
508				"-install_name @rpath/"+libName+toolchain.ShlibSuffix(),
509			)
510			if ctx.Arch().ArchType == android.X86 {
511				f = append(f,
512					"-read_only_relocs suppress",
513				)
514			}
515		} else {
516			f = append(f, "-shared")
517			if !ctx.Windows() {
518				f = append(f, "-Wl,-soname,"+libName+toolchain.ShlibSuffix())
519			}
520		}
521		flags.Global.LdFlags = append(flags.Global.LdFlags, f...)
522	}
523
524	return flags
525}
526
527// linkerFlags takes a Flags struct and augments it to contain linker flags that are defined by this
528// library, or that are implied by attributes of this library (such as whether this library is a
529// shared library).
530func (library *libraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
531	flags = library.baseLinker.linkerFlags(ctx, flags)
532	flags = CommonLibraryLinkerFlags(ctx, flags, ctx.toolchain(), library.getLibName(ctx))
533	if library.static() {
534		flags.Local.CFlags = append(flags.Local.CFlags, library.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)...)
535	} else if library.shared() {
536		flags.Local.CFlags = append(flags.Local.CFlags, library.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)...)
537	}
538
539	return flags
540}
541
542// compilerFlags takes a Flags and augments it to contain compile flags from global values,
543// per-target values, module type values, per-module Blueprints properties, extra flags from
544// `flags`, and generated sources from `deps`.
545func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
546	exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
547	if len(exportIncludeDirs) > 0 {
548		f := includeDirsToFlags(exportIncludeDirs)
549		flags.Local.CommonFlags = append(flags.Local.CommonFlags, f)
550		flags.Local.YasmFlags = append(flags.Local.YasmFlags, f)
551	}
552
553	flags = library.baseCompiler.compilerFlags(ctx, flags, deps)
554	if ctx.IsLlndk() {
555		// LLNDK libraries ignore most of the properties on the cc_library and use the
556		// LLNDK-specific properties instead.
557		// Wipe all the module-local properties, leaving only the global properties.
558		flags.Local = LocalOrGlobalFlags{}
559	}
560	if library.BuildStubs() {
561		// Remove -include <file> when compiling stubs. Otherwise, the force included
562		// headers might cause conflicting types error with the symbols in the
563		// generated stubs source code. e.g.
564		// double acos(double); // in header
565		// void acos() {} // in the generated source code
566		removeInclude := func(flags []string) []string {
567			ret := flags[:0]
568			for _, f := range flags {
569				if strings.HasPrefix(f, "-include ") {
570					continue
571				}
572				ret = append(ret, f)
573			}
574			return ret
575		}
576		flags.Local.CommonFlags = removeInclude(flags.Local.CommonFlags)
577		flags.Local.CFlags = removeInclude(flags.Local.CFlags)
578
579		flags = AddStubLibraryCompilerFlags(flags)
580	}
581	return flags
582}
583
584func (library *libraryDecorator) getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties {
585	variantProps := &library.Properties.Target.Platform.Header_abi_checker
586	if m.InVendor() {
587		variantProps = &library.Properties.Target.Vendor.Header_abi_checker
588	} else if m.InProduct() {
589		variantProps = &library.Properties.Target.Product.Header_abi_checker
590	}
591	props := library.Properties.Header_abi_checker
592	err := proptools.AppendProperties(&props, variantProps, nil)
593	if err != nil {
594		panic(fmt.Errorf("Cannot merge headerAbiCheckerProperties: %s", err.Error()))
595	}
596	return props
597}
598
599func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
600	sharedFlags := ctx.getSharedFlags()
601
602	if ctx.IsLlndk() {
603		// Get the matching SDK version for the vendor API level.
604		version, err := android.GetSdkVersionForVendorApiLevel(ctx.Config().VendorApiLevel())
605		if err != nil {
606			panic(err)
607		}
608
609		llndkFlag := "--llndk"
610		if ctx.baseModuleName() == "libbinder_ndk" && ctx.inProduct() {
611			// This is a special case only for the libbinder_ndk. As the product partition is in the
612			// framework side along with system and system_ext partitions in Treble, libbinder_ndk
613			// provides different binder interfaces between product and vendor modules.
614			// In libbinder_ndk, 'llndk' annotation is for the vendor APIs; while 'systemapi'
615			// annotation is for the product APIs.
616			// Use '--systemapi' flag for building the llndk stub of product variant for the
617			// libbinder_ndk.
618			llndkFlag = "--systemapi"
619		}
620
621		// This is the vendor variant of an LLNDK library, build the LLNDK stubs.
622		nativeAbiResult := ParseNativeAbiDefinition(ctx,
623			String(library.Properties.Llndk.Symbol_file),
624			nativeClampedApiLevel(ctx, version), llndkFlag)
625		objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, sharedFlags)
626		if !Bool(library.Properties.Llndk.Unversioned) {
627			library.versionScriptPath = android.OptionalPathForPath(
628				nativeAbiResult.VersionScript)
629		}
630		return objs
631	}
632	if ctx.IsVendorPublicLibrary() {
633		nativeAbiResult := ParseNativeAbiDefinition(ctx,
634			String(library.Properties.Vendor_public_library.Symbol_file),
635			android.FutureApiLevel, "")
636		objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, sharedFlags)
637		if !Bool(library.Properties.Vendor_public_library.Unversioned) {
638			library.versionScriptPath = android.OptionalPathForPath(nativeAbiResult.VersionScript)
639		}
640		return objs
641	}
642	if library.BuildStubs() {
643		return library.compileModuleLibApiStubs(ctx, flags, deps)
644	}
645
646	srcs := library.baseCompiler.Properties.Srcs.GetOrDefault(ctx, nil)
647	staticSrcs := library.StaticProperties.Static.Srcs.GetOrDefault(ctx, nil)
648	sharedSrcs := library.SharedProperties.Shared.Srcs.GetOrDefault(ctx, nil)
649	if !library.buildShared() && !library.buildStatic() {
650		if len(srcs) > 0 {
651			ctx.PropertyErrorf("srcs", "cc_library_headers must not have any srcs")
652		}
653		if len(staticSrcs) > 0 {
654			ctx.PropertyErrorf("static.srcs", "cc_library_headers must not have any srcs")
655		}
656		if len(sharedSrcs) > 0 {
657			ctx.PropertyErrorf("shared.srcs", "cc_library_headers must not have any srcs")
658		}
659		return Objects{}
660	}
661	if library.sabi.shouldCreateSourceAbiDump() {
662		dirs := library.exportedIncludeDirsForAbiCheck(ctx)
663		flags.SAbiFlags = make([]string, 0, len(dirs)+1)
664		for _, dir := range dirs {
665			flags.SAbiFlags = append(flags.SAbiFlags, "-I"+dir)
666		}
667		// If this library does not export any include directory, do not append the flags
668		// so that the ABI tool dumps everything without filtering by the include directories.
669		// requiresGlobalIncludes returns whether this library can include CommonGlobalIncludes.
670		// If the library cannot include them, it cannot export them.
671		if len(dirs) > 0 && requiresGlobalIncludes(ctx) {
672			flags.SAbiFlags = append(flags.SAbiFlags, "${config.CommonGlobalIncludes}")
673		}
674		totalLength := len(srcs) + len(deps.GeneratedSources) +
675			len(sharedSrcs) + len(staticSrcs)
676		if totalLength > 0 {
677			flags.SAbiDump = true
678		}
679	}
680	objs := library.baseCompiler.compile(ctx, flags, deps)
681	library.reuseObjects = objs
682	buildFlags := flagsToBuilderFlags(flags)
683
684	if library.static() {
685		srcs := android.PathsForModuleSrc(ctx, staticSrcs)
686		objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceStaticLibrary, srcs,
687			android.PathsForModuleSrc(ctx, library.StaticProperties.Static.Tidy_disabled_srcs),
688			android.PathsForModuleSrc(ctx, library.StaticProperties.Static.Tidy_timeout_srcs),
689			library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps, sharedFlags))
690	} else if library.shared() {
691		srcs := android.PathsForModuleSrc(ctx, sharedSrcs)
692		objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceSharedLibrary, srcs,
693			android.PathsForModuleSrc(ctx, library.SharedProperties.Shared.Tidy_disabled_srcs),
694			android.PathsForModuleSrc(ctx, library.SharedProperties.Shared.Tidy_timeout_srcs),
695			library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps, sharedFlags))
696	}
697
698	return objs
699}
700
701type ApiStubsParams struct {
702	NotInPlatform  bool
703	IsNdk          bool
704	BaseModuleName string
705	ModuleName     string
706}
707
708// GetApiStubsFlags calculates the genstubFlags string to pass to ParseNativeAbiDefinition
709func GetApiStubsFlags(api ApiStubsParams) string {
710	var flag string
711
712	// b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
713	// systemapi, respectively. The former is for symbols defined in platform libraries
714	// and the latter is for symbols defined in APEXes.
715	// A single library can contain either # apex or # systemapi, but not both.
716	// The stub generator (ndkstubgen) is additive, so passing _both_ of these to it should be a no-op.
717	// However, having this distinction helps guard accidental
718	// promotion or demotion of API and also helps the API review process b/191371676
719	if api.NotInPlatform {
720		flag = "--apex"
721	} else {
722		flag = "--systemapi"
723	}
724
725	// b/184712170, unless the lib is an NDK library, exclude all public symbols from
726	// the stub so that it is mandated that all symbols are explicitly marked with
727	// either apex or systemapi.
728	if !api.IsNdk &&
729		// the symbol files of libclang libs are autogenerated and do not contain systemapi tags
730		// TODO (spandandas): Update mapfile.py to include #systemapi tag on all symbols
731		!strings.Contains(api.ModuleName, "libclang_rt") {
732		flag = flag + " --no-ndk"
733	}
734
735	// TODO(b/361303067): Remove this special case if bionic/ projects are added to ART development branches.
736	if isBionic(api.BaseModuleName) {
737		// set the flags explicitly for bionic libs.
738		// this is necessary for development in minimal branches which does not contain bionic/*.
739		// In such minimal branches, e.g. on the prebuilt libc stubs
740		// 1. IsNdk will return false (since the ndk_library definition for libc does not exist)
741		// 2. NotInPlatform will return true (since the source com.android.runtime does not exist)
742		flag = "--apex"
743	}
744
745	return flag
746}
747
748// Compile stubs for the API surface between platform and apex
749// This method will be used by source and prebuilt cc module types.
750func (library *libraryDecorator) compileModuleLibApiStubs(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
751	// TODO (b/275273834): Make this a hard error when the symbol files have been added to module sdk.
752	if library.Properties.Stubs.Symbol_file == nil {
753		return Objects{}
754	}
755
756	symbolFile := String(library.Properties.Stubs.Symbol_file)
757	library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile)
758
759	apiParams := ApiStubsParams{
760		NotInPlatform:  ctx.notInPlatform(),
761		IsNdk:          ctx.Module().(*Module).IsNdk(ctx.Config()),
762		BaseModuleName: ctx.baseModuleName(),
763		ModuleName:     ctx.ModuleName(),
764	}
765	flag := GetApiStubsFlags(apiParams)
766
767	nativeAbiResult := ParseNativeAbiDefinition(ctx, symbolFile,
768		android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
769	objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, ctx.getSharedFlags())
770
771	library.versionScriptPath = android.OptionalPathForPath(
772		nativeAbiResult.VersionScript)
773	// Parse symbol file to get API list for coverage
774	if library.StubsVersion() == "current" && ctx.PrimaryArch() && !ctx.inRecovery() && !ctx.inProduct() && !ctx.inVendor() {
775		library.apiListCoverageXmlPath = ParseSymbolFileForAPICoverage(ctx, symbolFile)
776	}
777
778	return objs
779}
780
781type libraryInterface interface {
782	VersionedInterface
783
784	static() bool
785	shared() bool
786	objs() Objects
787	reuseObjs() Objects
788	toc() android.OptionalPath
789
790	// Returns true if the build options for the module have selected a static or shared build
791	buildStatic() bool
792	buildShared() bool
793
794	// Sets whether a specific variant is static or shared
795	setStatic()
796	setShared()
797
798	// Gets the ABI properties for vendor, product, or platform variant
799	getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties
800
801	// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
802	androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
803
804	apexAvailable() []string
805
806	setAPIListCoverageXMLPath(out android.ModuleOutPath)
807	symbolsFile() *string
808	setSymbolFilePath(path android.Path)
809	setVersionScriptPath(path android.OptionalPath)
810
811	installable() *bool
812}
813
814func (library *libraryDecorator) symbolsFile() *string {
815	return library.Properties.Stubs.Symbol_file
816}
817
818func (library *libraryDecorator) setSymbolFilePath(path android.Path) {
819	library.stubsSymbolFilePath = path
820}
821
822func (library *libraryDecorator) setVersionScriptPath(path android.OptionalPath) {
823	library.versionScriptPath = path
824}
825
826type VersionedInterface interface {
827	BuildStubs() bool
828	SetBuildStubs(isLatest bool)
829	HasStubsVariants() bool
830	IsStubsImplementationRequired() bool
831	SetStubsVersion(string)
832	StubsVersion() string
833
834	StubsVersions(ctx android.BaseModuleContext) []string
835	SetAllStubsVersions([]string)
836	AllStubsVersions() []string
837
838	ImplementationModuleName(name string) string
839	HasLLNDKStubs() bool
840	HasLLNDKHeaders() bool
841	HasVendorPublicLibrary() bool
842	IsLLNDKMovedToApex() bool
843
844	GetAPIListCoverageXMLPath() android.ModuleOutPath
845}
846
847var _ libraryInterface = (*libraryDecorator)(nil)
848var _ VersionedInterface = (*libraryDecorator)(nil)
849
850func (library *libraryDecorator) getLibNameHelper(baseModuleName string, inVendor bool, inProduct bool) string {
851	name := library.libName
852	if name == "" {
853		name = String(library.Properties.Stem)
854		if name == "" {
855			name = baseModuleName
856		}
857	}
858
859	suffix := ""
860	if inVendor {
861		suffix = String(library.Properties.Target.Vendor.Suffix)
862	} else if inProduct {
863		suffix = String(library.Properties.Target.Product.Suffix)
864	}
865	if suffix == "" {
866		suffix = String(library.Properties.Suffix)
867	}
868
869	return name + suffix
870}
871
872// getLibName returns the actual canonical name of the library (the name which
873// should be passed to the linker via linker flags).
874func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
875	name := library.getLibNameHelper(ctx.baseModuleName(), ctx.inVendor(), ctx.inProduct())
876
877	if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
878		if !strings.HasSuffix(name, "-host") {
879			name = name + "-host"
880		}
881	}
882
883	return name
884}
885
886var versioningMacroNamesListMutex sync.Mutex
887
888func (library *libraryDecorator) linkerInit(ctx BaseModuleContext) {
889	location := InstallInSystem
890	if library.baseLinker.sanitize.inSanitizerDir() {
891		location = InstallInSanitizerDir
892	}
893	library.baseInstaller.location = location
894	library.baseLinker.linkerInit(ctx)
895	// Let baseLinker know whether this variant is for stubs or not, so that
896	// it can omit things that are not required for linking stubs.
897	library.baseLinker.dynamicProperties.BuildStubs = library.BuildStubs()
898
899	if library.BuildStubs() {
900		macroNames := versioningMacroNamesList(ctx.Config())
901		myName := versioningMacroName(ctx.ModuleName())
902		versioningMacroNamesListMutex.Lock()
903		defer versioningMacroNamesListMutex.Unlock()
904		if (*macroNames)[myName] == "" {
905			(*macroNames)[myName] = ctx.ModuleName()
906		} else if (*macroNames)[myName] != ctx.ModuleName() {
907			ctx.ModuleErrorf("Macro name %q for versioning conflicts with macro name from module %q ", myName, (*macroNames)[myName])
908		}
909	}
910}
911
912func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
913	if ctx.IsLlndk() {
914		// LLNDK libraries ignore most of the properties on the cc_library and use the
915		// LLNDK-specific properties instead.
916		return deps
917	}
918
919	deps = library.baseCompiler.compilerDeps(ctx, deps)
920
921	return deps
922}
923
924func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
925	if ctx.IsLlndk() {
926		// LLNDK libraries ignore most of the properties on the cc_library and use the
927		// LLNDK-specific properties instead.
928		deps.HeaderLibs = append([]string(nil), library.Properties.Llndk.Export_llndk_headers...)
929		deps.ReexportHeaderLibHeaders = append([]string(nil), library.Properties.Llndk.Export_llndk_headers...)
930		return deps
931	}
932	if ctx.IsVendorPublicLibrary() {
933		headers := library.Properties.Vendor_public_library.Export_public_headers
934		deps.HeaderLibs = append([]string(nil), headers...)
935		deps.ReexportHeaderLibHeaders = append([]string(nil), headers...)
936		return deps
937	}
938
939	if library.static() {
940		// Compare with nil because an empty list needs to be propagated.
941		if library.StaticProperties.Static.System_shared_libs != nil {
942			library.baseLinker.Properties.System_shared_libs = library.StaticProperties.Static.System_shared_libs
943		}
944	} else if library.shared() {
945		// Compare with nil because an empty list needs to be propagated.
946		if library.SharedProperties.Shared.System_shared_libs != nil {
947			library.baseLinker.Properties.System_shared_libs = library.SharedProperties.Shared.System_shared_libs
948		}
949	}
950
951	deps = library.baseLinker.linkerDeps(ctx, deps)
952
953	if library.static() {
954		deps.WholeStaticLibs = append(deps.WholeStaticLibs,
955			library.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)...)
956		deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)...)
957		deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)...)
958
959		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.StaticProperties.Static.Export_shared_lib_headers...)
960		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.StaticProperties.Static.Export_static_lib_headers...)
961	} else if library.shared() {
962		if library.baseLinker.Properties.crt() {
963			deps.CrtBegin = append(deps.CrtBegin, ctx.toolchain().CrtBeginSharedLibrary()...)
964			deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtEndSharedLibrary()...)
965
966		}
967		if library.baseLinker.Properties.crtPadSegment() {
968			deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtPadSegmentSharedLibrary()...)
969		}
970		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)...)
971		deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)...)
972		deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)...)
973
974		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.SharedProperties.Shared.Export_shared_lib_headers...)
975		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.SharedProperties.Shared.Export_static_lib_headers...)
976
977		deps.LlndkHeaderLibs = append(deps.LlndkHeaderLibs, library.Properties.Llndk.Export_llndk_headers...)
978	}
979	if ctx.inVendor() {
980		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
981		deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs)
982		deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
983		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs)
984		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
985	}
986	if ctx.inProduct() {
987		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Product.Exclude_static_libs)
988		deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Product.Exclude_shared_libs)
989		deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Product.Exclude_static_libs)
990		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Product.Exclude_shared_libs)
991		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Product.Exclude_static_libs)
992	}
993	if ctx.inRecovery() {
994		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
995		deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Recovery.Exclude_shared_libs)
996		deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
997		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Recovery.Exclude_shared_libs)
998		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
999	}
1000	if ctx.inRamdisk() {
1001		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Ramdisk.Exclude_static_libs)
1002		deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Ramdisk.Exclude_shared_libs)
1003		deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Ramdisk.Exclude_static_libs)
1004		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Ramdisk.Exclude_shared_libs)
1005		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Ramdisk.Exclude_static_libs)
1006	}
1007	if ctx.inVendorRamdisk() {
1008		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
1009		deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
1010		deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
1011		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
1012		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
1013	}
1014
1015	return deps
1016}
1017
1018func (library *libraryDecorator) linkerSpecifiedDeps(ctx android.ConfigurableEvaluatorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
1019	specifiedDeps = library.baseLinker.linkerSpecifiedDeps(ctx, module, specifiedDeps)
1020	var properties StaticOrSharedProperties
1021	if library.static() {
1022		properties = library.StaticProperties.Static
1023	} else if library.shared() {
1024		properties = library.SharedProperties.Shared
1025	}
1026
1027	eval := module.ConfigurableEvaluator(ctx)
1028	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs.GetOrDefault(eval, nil)...)
1029
1030	// Must distinguish nil and [] in system_shared_libs - ensure that [] in
1031	// either input list doesn't come out as nil.
1032	if specifiedDeps.systemSharedLibs == nil {
1033		specifiedDeps.systemSharedLibs = properties.System_shared_libs
1034	} else {
1035		specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, properties.System_shared_libs...)
1036	}
1037
1038	specifiedDeps.sharedLibs = android.FirstUniqueStrings(specifiedDeps.sharedLibs)
1039	if len(specifiedDeps.systemSharedLibs) > 0 {
1040		// Skip this if systemSharedLibs is either nil or [], to ensure they are
1041		// retained.
1042		specifiedDeps.systemSharedLibs = android.FirstUniqueStrings(specifiedDeps.systemSharedLibs)
1043	}
1044	return specifiedDeps
1045}
1046
1047func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
1048	if library.static() {
1049		moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
1050		moduleInfoJSON.Uninstallable = true
1051	} else if library.shared() {
1052		moduleInfoJSON.Class = []string{"SHARED_LIBRARIES"}
1053	} else if library.header() {
1054		moduleInfoJSON.Class = []string{"HEADER_LIBRARIES"}
1055		moduleInfoJSON.Uninstallable = true
1056	}
1057
1058	if library.BuildStubs() && library.StubsVersion() != "" {
1059		moduleInfoJSON.SubName += "." + library.StubsVersion()
1060	}
1061
1062	// If a library providing a stub is included in an APEX, the private APIs of the library
1063	// is accessible only inside the APEX. From outside of the APEX, clients can only use the
1064	// public APIs via the stub. To enforce this, the (latest version of the) stub gets the
1065	// name of the library. The impl library instead gets the `.bootstrap` suffix to so that
1066	// they can be exceptionally used directly when APEXes are not available (e.g. during the
1067	// very early stage in the boot process).
1068	if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.notInPlatform() &&
1069		!ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && !ctx.useVndk() && !ctx.static() {
1070		if library.BuildStubs() && library.isLatestStubVersion() {
1071			moduleInfoJSON.SubName = ""
1072		}
1073		if !library.BuildStubs() {
1074			moduleInfoJSON.SubName = ".bootstrap"
1075		}
1076	}
1077
1078	library.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
1079}
1080
1081func (library *libraryDecorator) testSuiteInfo(ctx ModuleContext) {
1082	// not a test
1083}
1084
1085func (library *libraryDecorator) linkStatic(ctx ModuleContext,
1086	flags Flags, deps PathDeps, objs Objects) android.Path {
1087
1088	library.objects = deps.WholeStaticLibObjs.Copy()
1089	library.objects = library.objects.Append(objs)
1090	library.wholeStaticLibsFromPrebuilts = android.CopyOfPaths(deps.WholeStaticLibsFromPrebuilts)
1091
1092	if library.wideStaticlibForMake {
1093		if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
1094			// WholeStaticLibsFromPrebuilts are .a files that get included whole into the resulting staticlib
1095			// so reuse that here for our Rust staticlibs because we don't have individual object files for
1096			// these.
1097			deps.WholeStaticLibsFromPrebuilts = append(deps.WholeStaticLibsFromPrebuilts, generatedLib)
1098		}
1099
1100	}
1101
1102	fileName := ctx.ModuleName() + staticLibraryExtension
1103	outputFile := android.PathForModuleOut(ctx, fileName)
1104	builderFlags := flagsToBuilderFlags(flags)
1105
1106	if Bool(library.baseLinker.Properties.Use_version_lib) {
1107		if ctx.Host() {
1108			versionedOutputFile := outputFile
1109			outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
1110			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
1111		} else {
1112			versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
1113			library.defaultDistFile = versionedOutputFile
1114			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
1115		}
1116	}
1117
1118	transformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, nil, objs.tidyDepFiles)
1119
1120	library.coverageOutputFile = transformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
1121
1122	ctx.CheckbuildFile(outputFile)
1123
1124	if library.static() {
1125		android.SetProvider(ctx, StaticLibraryInfoProvider, StaticLibraryInfo{
1126			StaticLibrary:                outputFile,
1127			ReuseObjects:                 library.reuseObjects,
1128			Objects:                      library.objects,
1129			WholeStaticLibsFromPrebuilts: library.wholeStaticLibsFromPrebuilts,
1130
1131			TransitiveStaticLibrariesForOrdering: depset.NewBuilder[android.Path](depset.TOPOLOGICAL).
1132				Direct(outputFile).
1133				Transitive(deps.TranstiveStaticLibrariesForOrdering).
1134				Build(),
1135		})
1136	}
1137
1138	if library.header() {
1139		android.SetProvider(ctx, HeaderLibraryInfoProvider, HeaderLibraryInfo{})
1140	}
1141
1142	return outputFile
1143}
1144
1145func ndkSharedLibDeps(ctx ModuleContext) android.Paths {
1146	if ctx.Module().(*Module).IsSdkVariant() {
1147		// The NDK sysroot timestamp file depends on all the NDK
1148		// sysroot header and shared library files.
1149		return android.Paths{getNdkBaseTimestampFile(ctx)}
1150	}
1151	return nil
1152}
1153
1154func (library *libraryDecorator) linkShared(ctx ModuleContext,
1155	flags Flags, deps PathDeps, objs Objects) android.Path {
1156
1157	var linkerDeps android.Paths
1158	linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
1159	linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...)
1160
1161	exportedSymbols := ctx.ExpandOptionalSource(library.Properties.Exported_symbols_list, "exported_symbols_list")
1162	unexportedSymbols := ctx.ExpandOptionalSource(library.Properties.Unexported_symbols_list, "unexported_symbols_list")
1163	forceNotWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_not_weak_list, "force_symbols_not_weak_list")
1164	forceWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_weak_list, "force_symbols_weak_list")
1165	if !ctx.Darwin() {
1166		if exportedSymbols.Valid() {
1167			ctx.PropertyErrorf("exported_symbols_list", "Only supported on Darwin")
1168		}
1169		if unexportedSymbols.Valid() {
1170			ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
1171		}
1172		if forceNotWeakSymbols.Valid() {
1173			ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
1174		}
1175		if forceWeakSymbols.Valid() {
1176			ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
1177		}
1178	} else {
1179		if exportedSymbols.Valid() {
1180			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-exported_symbols_list,"+exportedSymbols.String())
1181			linkerDeps = append(linkerDeps, exportedSymbols.Path())
1182		}
1183		if unexportedSymbols.Valid() {
1184			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
1185			linkerDeps = append(linkerDeps, unexportedSymbols.Path())
1186		}
1187		if forceNotWeakSymbols.Valid() {
1188			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
1189			linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
1190		}
1191		if forceWeakSymbols.Valid() {
1192			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
1193			linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
1194		}
1195	}
1196	if library.versionScriptPath.Valid() {
1197		linkerScriptFlags := "-Wl,--version-script," + library.versionScriptPath.String()
1198		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlags)
1199		linkerDeps = append(linkerDeps, library.versionScriptPath.Path())
1200	}
1201
1202	fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
1203	outputFile := android.PathForModuleOut(ctx, fileName)
1204	unstrippedOutputFile := outputFile
1205
1206	var implicitOutputs android.WritablePaths
1207	if ctx.Windows() {
1208		importLibraryPath := android.PathForModuleOut(ctx, pathtools.ReplaceExtension(fileName, "lib"))
1209
1210		flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--out-implib="+importLibraryPath.String())
1211		implicitOutputs = append(implicitOutputs, importLibraryPath)
1212	}
1213
1214	builderFlags := flagsToBuilderFlags(flags)
1215
1216	if ctx.Darwin() && deps.DarwinSecondArchOutput.Valid() {
1217		fatOutputFile := outputFile
1218		outputFile = android.PathForModuleOut(ctx, "pre-fat", fileName)
1219		transformDarwinUniversalBinary(ctx, fatOutputFile, outputFile, deps.DarwinSecondArchOutput.Path())
1220	}
1221
1222	// Optimize out relinking against shared libraries whose interface hasn't changed by
1223	// depending on a table of contents file instead of the library itself.
1224	tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
1225	library.tocFile = android.OptionalPathForPath(tocFile)
1226	TransformSharedObjectToToc(ctx, outputFile, tocFile)
1227
1228	stripFlags := flagsToStripFlags(flags)
1229	needsStrip := library.stripper.NeedsStrip(ctx)
1230	if library.BuildStubs() {
1231		// No need to strip stubs libraries
1232		needsStrip = false
1233	}
1234	if needsStrip {
1235		if ctx.Darwin() {
1236			stripFlags.StripUseGnuStrip = true
1237		}
1238		strippedOutputFile := outputFile
1239		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
1240		library.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile, stripFlags)
1241	}
1242	library.unstrippedOutputFile = outputFile
1243
1244	outputFile = maybeInjectBoringSSLHash(ctx, outputFile, library.Properties.Inject_bssl_hash, fileName)
1245
1246	if Bool(library.baseLinker.Properties.Use_version_lib) {
1247		if ctx.Host() {
1248			versionedOutputFile := outputFile
1249			outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
1250			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
1251		} else {
1252			versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
1253			library.defaultDistFile = versionedOutputFile
1254
1255			if library.stripper.NeedsStrip(ctx) {
1256				out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
1257				library.defaultDistFile = out
1258				library.stripper.StripExecutableOrSharedLib(ctx, versionedOutputFile, out, stripFlags)
1259			}
1260
1261			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
1262		}
1263	}
1264
1265	// Generate an output file for dist as if strip: "all" is set on the module.
1266	// Currently this is for layoutlib release process only.
1267	for _, dist := range ctx.Module().(*Module).Dists() {
1268		if dist.Tag != nil && *dist.Tag == "stripped_all" {
1269			strippedAllOutputFile := android.PathForModuleOut(ctx, "stripped_all", fileName)
1270			transformStrip(ctx, outputFile, strippedAllOutputFile, StripFlags{Toolchain: flags.Toolchain})
1271			library.strippedAllOutputFile = strippedAllOutputFile
1272			break
1273		}
1274	}
1275
1276	sharedLibs := deps.EarlySharedLibs
1277	sharedLibs = append(sharedLibs, deps.SharedLibs...)
1278	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
1279
1280	linkerDeps = append(linkerDeps, deps.EarlySharedLibsDeps...)
1281	linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
1282	linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
1283
1284	if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil && !library.BuildStubs() {
1285		if ctx.Module().(*Module).WholeRustStaticlib {
1286			deps.WholeStaticLibs = append(deps.WholeStaticLibs, generatedLib)
1287		} else {
1288			deps.StaticLibs = append(deps.StaticLibs, generatedLib)
1289		}
1290	}
1291
1292	transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
1293		deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin,
1294		deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyDepFiles)
1295
1296	objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
1297	objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
1298	objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.StaticLibObjs.sAbiDumpFiles...)
1299	objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...)
1300
1301	library.coverageOutputFile = transformCoverageFilesToZip(ctx, objs, library.getLibName(ctx))
1302	library.linkSAbiDumpFiles(ctx, deps, objs, fileName, unstrippedOutputFile)
1303
1304	var transitiveStaticLibrariesForOrdering depset.DepSet[android.Path]
1305	if static := ctx.GetDirectDepsProxyWithTag(staticVariantTag); len(static) > 0 {
1306		s, _ := android.OtherModuleProvider(ctx, static[0], StaticLibraryInfoProvider)
1307		transitiveStaticLibrariesForOrdering = s.TransitiveStaticLibrariesForOrdering
1308	}
1309
1310	android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
1311		TableOfContents:                      android.OptionalPathForPath(tocFile),
1312		SharedLibrary:                        unstrippedOutputFile,
1313		TransitiveStaticLibrariesForOrdering: transitiveStaticLibrariesForOrdering,
1314		Target:                               ctx.Target(),
1315		IsStubs:                              library.BuildStubs(),
1316	})
1317
1318	AddStubDependencyProviders(ctx)
1319
1320	return unstrippedOutputFile
1321}
1322
1323// Visits the stub variants of the library and returns a struct containing the stub .so paths
1324func AddStubDependencyProviders(ctx android.BaseModuleContext) []SharedStubLibrary {
1325	stubsInfo := []SharedStubLibrary{}
1326	stubs := ctx.GetDirectDepsProxyWithTag(StubImplDepTag)
1327	if len(stubs) > 0 {
1328		for _, stub := range stubs {
1329			stubInfo, ok := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
1330			// TODO (b/275273834): Make this a hard error when the symbol files have been added to module sdk.
1331			if !ok {
1332				continue
1333			}
1334			flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
1335			if _, ok = android.OtherModuleProvider(ctx, stub, CcInfoProvider); !ok {
1336				panic(fmt.Errorf("stub is not a cc module %s", stub))
1337			}
1338			stubsInfo = append(stubsInfo, SharedStubLibrary{
1339				Version:           android.OtherModuleProviderOrDefault(ctx, stub, LinkableInfoProvider).StubsVersion,
1340				SharedLibraryInfo: stubInfo,
1341				FlagExporterInfo:  flagInfo,
1342			})
1343		}
1344		if len(stubsInfo) > 0 {
1345			android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
1346				SharedStubLibraries: stubsInfo,
1347				IsLLNDK:             ctx.Module().(LinkableInterface).IsLlndk(),
1348			})
1349		}
1350	}
1351
1352	return stubsInfo
1353}
1354
1355func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
1356	return library.unstrippedOutputFile
1357}
1358
1359func (library *libraryDecorator) strippedAllOutputFilePath() android.Path {
1360	return library.strippedAllOutputFile
1361}
1362
1363func (library *libraryDecorator) disableStripping() {
1364	library.stripper.StripProperties.Strip.None = BoolPtr(true)
1365}
1366
1367func (library *libraryDecorator) nativeCoverage() bool {
1368	if library.header() || library.BuildStubs() {
1369		return false
1370	}
1371	return true
1372}
1373
1374func (library *libraryDecorator) coverageOutputFilePath() android.OptionalPath {
1375	return library.coverageOutputFile
1376}
1377
1378func (library *libraryDecorator) exportedIncludeDirsForAbiCheck(ctx ModuleContext) []string {
1379	exportIncludeDirs := library.flagExporter.exportedIncludes(ctx).Strings()
1380	exportIncludeDirs = append(exportIncludeDirs, library.sabi.Properties.ReexportedIncludes...)
1381	exportSystemIncludeDirs := library.flagExporter.exportedSystemIncludes(ctx).Strings()
1382	exportSystemIncludeDirs = append(exportSystemIncludeDirs, library.sabi.Properties.ReexportedSystemIncludes...)
1383	// The ABI checker does not distinguish normal and system headers.
1384	return append(exportIncludeDirs, exportSystemIncludeDirs...)
1385}
1386
1387func (library *libraryDecorator) llndkIncludeDirsForAbiCheck(ctx ModuleContext, deps PathDeps) []string {
1388	var includeDirs, systemIncludeDirs []string
1389
1390	if library.Properties.Llndk.Override_export_include_dirs != nil {
1391		includeDirs = append(includeDirs, android.PathsForModuleSrc(
1392			ctx, library.Properties.Llndk.Override_export_include_dirs).Strings()...)
1393	} else {
1394		includeDirs = append(includeDirs, library.flagExporter.exportedIncludes(ctx).Strings()...)
1395		// Ignore library.sabi.Properties.ReexportedIncludes because
1396		// LLNDK does not reexport the implementation's dependencies, such as export_header_libs.
1397	}
1398
1399	systemIncludeDirs = append(systemIncludeDirs,
1400		library.flagExporter.exportedSystemIncludes(ctx).Strings()...)
1401	if Bool(library.Properties.Llndk.Export_headers_as_system) {
1402		systemIncludeDirs = append(systemIncludeDirs, includeDirs...)
1403		includeDirs = nil
1404	}
1405	// Header libs.
1406	includeDirs = append(includeDirs, deps.LlndkIncludeDirs.Strings()...)
1407	systemIncludeDirs = append(systemIncludeDirs, deps.LlndkSystemIncludeDirs.Strings()...)
1408	// The ABI checker does not distinguish normal and system headers.
1409	return append(includeDirs, systemIncludeDirs...)
1410}
1411
1412func (library *libraryDecorator) linkLlndkSAbiDumpFiles(ctx ModuleContext,
1413	deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string,
1414	excludeSymbolVersions, excludeSymbolTags []string,
1415	sdkVersionForVendorApiLevel string) android.Path {
1416	// Though LLNDK is implemented in system, the callers in vendor cannot include CommonGlobalIncludes,
1417	// so commonGlobalIncludes is false.
1418	return transformDumpToLinkedDump(ctx,
1419		sAbiDumpFiles, soFile, libFileName+".llndk",
1420		library.llndkIncludeDirsForAbiCheck(ctx, deps),
1421		android.OptionalPathForModuleSrc(ctx, library.Properties.Llndk.Symbol_file),
1422		append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
1423		append([]string{"platform-only"}, excludeSymbolTags...),
1424		[]string{"llndk"}, sdkVersionForVendorApiLevel, false /* commonGlobalIncludes */)
1425}
1426
1427func (library *libraryDecorator) linkApexSAbiDumpFiles(ctx ModuleContext,
1428	deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string,
1429	excludeSymbolVersions, excludeSymbolTags []string,
1430	sdkVersion string) android.Path {
1431	return transformDumpToLinkedDump(ctx,
1432		sAbiDumpFiles, soFile, libFileName+".apex",
1433		library.exportedIncludeDirsForAbiCheck(ctx),
1434		android.OptionalPathForModuleSrc(ctx, library.Properties.Stubs.Symbol_file),
1435		append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
1436		append([]string{"platform-only"}, excludeSymbolTags...),
1437		[]string{"apex", "systemapi"}, sdkVersion, requiresGlobalIncludes(ctx))
1438}
1439
1440func getRefAbiDumpFile(ctx android.ModuleInstallPathContext,
1441	versionedDumpDir, fileName string) android.OptionalPath {
1442
1443	currentArchType := ctx.Arch().ArchType
1444	primaryArchType := ctx.Config().DevicePrimaryArchType()
1445	archName := currentArchType.String()
1446	if currentArchType != primaryArchType {
1447		archName += "_" + primaryArchType.String()
1448	}
1449
1450	return android.ExistentPathForSource(ctx, versionedDumpDir, archName, "source-based",
1451		fileName+".lsdump")
1452}
1453
1454// Return the previous and current SDK versions for cross-version ABI diff.
1455func crossVersionAbiDiffSdkVersions(ctx ModuleContext, dumpDir string) (int, int) {
1456	sdkVersionInt := ctx.Config().PlatformSdkVersion().FinalInt()
1457
1458	if ctx.Config().PlatformSdkFinal() {
1459		return sdkVersionInt - 1, sdkVersionInt
1460	} else {
1461		// The platform SDK version can be upgraded before finalization while the corresponding abi dumps hasn't
1462		// been generated. Thus the Cross-Version Check chooses PLATFORM_SDK_VERION - 1 as previous version.
1463		// This situation could be identified by checking the existence of the PLATFORM_SDK_VERION dump directory.
1464		versionedDumpDir := android.ExistentPathForSource(ctx,
1465			dumpDir, ctx.Config().PlatformSdkVersion().String())
1466		if versionedDumpDir.Valid() {
1467			return sdkVersionInt, sdkVersionInt + 1
1468		} else {
1469			return sdkVersionInt - 1, sdkVersionInt
1470		}
1471	}
1472}
1473
1474// Return the SDK version for same-version ABI diff.
1475func currRefAbiDumpSdkVersion(ctx ModuleContext) string {
1476	if ctx.Config().PlatformSdkFinal() {
1477		// After sdk finalization, the ABI of the latest API level must be consistent with the source code,
1478		// so choose PLATFORM_SDK_VERSION as the current version.
1479		return ctx.Config().PlatformSdkVersion().String()
1480	} else {
1481		return "current"
1482	}
1483}
1484
1485// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
1486func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext,
1487	sourceDump, referenceDump android.Path,
1488	baseName, nameExt string, isLlndk, allowExtensions bool,
1489	sourceVersion, errorMessage string) {
1490
1491	extraFlags := []string{"-target-version", sourceVersion}
1492	headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module))
1493	if Bool(headerAbiChecker.Check_all_apis) {
1494		extraFlags = append(extraFlags, "-check-all-apis")
1495	} else {
1496		extraFlags = append(extraFlags,
1497			"-allow-unreferenced-changes",
1498			"-allow-unreferenced-elf-symbol-changes")
1499		// The functions in standard libraries are not always declared in the headers.
1500		// Allow them to be added or removed without changing the symbols.
1501		if isBionic(ctx.ModuleName()) {
1502			extraFlags = append(extraFlags, "-allow-adding-removing-referenced-apis")
1503		}
1504	}
1505	if isLlndk {
1506		extraFlags = append(extraFlags, "-consider-opaque-types-different")
1507	}
1508	if allowExtensions {
1509		extraFlags = append(extraFlags, "-allow-extensions")
1510	}
1511	extraFlags = append(extraFlags, headerAbiChecker.Diff_flags...)
1512
1513	library.sAbiDiff = append(
1514		library.sAbiDiff,
1515		transformAbiDumpToAbiDiff(ctx, sourceDump, referenceDump,
1516			baseName, nameExt, extraFlags, errorMessage))
1517}
1518
1519func (library *libraryDecorator) crossVersionAbiDiff(ctx android.ModuleContext,
1520	sourceDump, referenceDump android.Path,
1521	baseName, nameExt string, isLlndk bool, sourceVersion, prevDumpDir string) {
1522
1523	errorMessage := "error: Please follow https://android.googlesource.com/platform/development/+/main/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the difference between your source code and the ABI dumps in " + prevDumpDir
1524
1525	library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
1526		isLlndk, true /* allowExtensions */, sourceVersion, errorMessage)
1527}
1528
1529func (library *libraryDecorator) sameVersionAbiDiff(ctx android.ModuleContext,
1530	sourceDump, referenceDump android.Path,
1531	baseName, nameExt string, isLlndk bool, lsdumpTagName string) {
1532
1533	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
1534	errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py --lib " + libName + " --lib-variant " + lsdumpTagName
1535
1536	targetRelease := ctx.Config().Getenv("TARGET_RELEASE")
1537	if targetRelease != "" {
1538		errorMessage += " --release " + targetRelease
1539	}
1540
1541	library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
1542		isLlndk, false /* allowExtensions */, "current", errorMessage)
1543}
1544
1545func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext,
1546	sourceDump, referenceDump android.Path,
1547	baseName, nameExt string, refDumpDir string, lsdumpTagName string) {
1548
1549	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
1550	errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py --lib " + libName + " --lib-variant " + lsdumpTagName + " --ref-dump-dir $$ANDROID_BUILD_TOP/" + refDumpDir
1551
1552	targetRelease := ctx.Config().Getenv("TARGET_RELEASE")
1553	if targetRelease != "" {
1554		errorMessage += " --release " + targetRelease
1555	}
1556
1557	// Most opt-in libraries do not have dumps for all default architectures.
1558	if ctx.Config().HasDeviceProduct() {
1559		errorMessage += " --product " + ctx.Config().DeviceProduct()
1560	}
1561
1562	library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
1563		false /* isLlndk */, false /* allowExtensions */, "current", errorMessage)
1564}
1565
1566func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathDeps, objs Objects, fileName string, soFile android.Path) {
1567	if library.sabi.shouldCreateSourceAbiDump() {
1568		exportedIncludeDirs := library.exportedIncludeDirsForAbiCheck(ctx)
1569		headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module))
1570		currSdkVersion := currRefAbiDumpSdkVersion(ctx)
1571		currVendorVersion := ctx.Config().VendorApiLevel()
1572
1573		// Generate source dumps.
1574		implDump := transformDumpToLinkedDump(ctx,
1575			objs.sAbiDumpFiles, soFile, fileName,
1576			exportedIncludeDirs,
1577			android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
1578			headerAbiChecker.Exclude_symbol_versions,
1579			headerAbiChecker.Exclude_symbol_tags,
1580			[]string{} /* includeSymbolTags */, currSdkVersion, requiresGlobalIncludes(ctx))
1581
1582		var llndkDump, apexVariantDump android.Path
1583		tags := classifySourceAbiDump(ctx.Module().(*Module))
1584		optInTags := []lsdumpTag{}
1585		for _, tag := range tags {
1586			if tag == llndkLsdumpTag && currVendorVersion != "" {
1587				if llndkDump == nil {
1588					sdkVersion, err := android.GetSdkVersionForVendorApiLevel(currVendorVersion)
1589					if err != nil {
1590						ctx.ModuleErrorf("Cannot create %s llndk dump: %s", fileName, err)
1591						return
1592					}
1593					// TODO(b/323447559): Evaluate if replacing sAbiDumpFiles with implDump is faster
1594					llndkDump = library.linkLlndkSAbiDumpFiles(ctx,
1595						deps, objs.sAbiDumpFiles, soFile, fileName,
1596						headerAbiChecker.Exclude_symbol_versions,
1597						headerAbiChecker.Exclude_symbol_tags,
1598						nativeClampedApiLevel(ctx, sdkVersion).String())
1599				}
1600				addLsdumpPath(ctx.Config(), string(tag)+":"+llndkDump.String())
1601			} else if tag == apexLsdumpTag {
1602				if apexVariantDump == nil {
1603					apexVariantDump = library.linkApexSAbiDumpFiles(ctx,
1604						deps, objs.sAbiDumpFiles, soFile, fileName,
1605						headerAbiChecker.Exclude_symbol_versions,
1606						headerAbiChecker.Exclude_symbol_tags,
1607						currSdkVersion)
1608				}
1609				addLsdumpPath(ctx.Config(), string(tag)+":"+apexVariantDump.String())
1610			} else {
1611				if tag.dirName() == "" {
1612					optInTags = append(optInTags, tag)
1613				}
1614				addLsdumpPath(ctx.Config(), string(tag)+":"+implDump.String())
1615			}
1616		}
1617
1618		// Diff source dumps and reference dumps.
1619		for _, tag := range tags {
1620			dumpDirName := tag.dirName()
1621			if dumpDirName == "" {
1622				continue
1623			}
1624			dumpDir := filepath.Join("prebuilts", "abi-dumps", dumpDirName)
1625			isLlndk := (tag == llndkLsdumpTag)
1626			isApex := (tag == apexLsdumpTag)
1627			binderBitness := ctx.DeviceConfig().BinderBitness()
1628			nameExt := ""
1629			if isLlndk {
1630				nameExt = "llndk"
1631			} else if isApex {
1632				nameExt = "apex"
1633			}
1634			// Check against the previous version.
1635			var prevVersion, currVersion string
1636			sourceDump := implDump
1637			// If this release config does not define VendorApiLevel, fall back to the old policy.
1638			if isLlndk && currVendorVersion != "" {
1639				prevVersion = ctx.Config().PrevVendorApiLevel()
1640				currVersion = currVendorVersion
1641				// LLNDK dumps are generated by different rules after trunk stable.
1642				if android.IsTrunkStableVendorApiLevel(prevVersion) {
1643					sourceDump = llndkDump
1644				}
1645			} else {
1646				prevVersionInt, currVersionInt := crossVersionAbiDiffSdkVersions(ctx, dumpDir)
1647				prevVersion = strconv.Itoa(prevVersionInt)
1648				currVersion = strconv.Itoa(currVersionInt)
1649				// APEX dumps are generated by different rules after trunk stable.
1650				if isApex && prevVersionInt > 34 {
1651					sourceDump = apexVariantDump
1652				}
1653			}
1654			prevDumpDir := filepath.Join(dumpDir, prevVersion, binderBitness)
1655			prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
1656			if prevDumpFile.Valid() {
1657				library.crossVersionAbiDiff(ctx, sourceDump, prevDumpFile.Path(),
1658					fileName, nameExt+prevVersion, isLlndk, currVersion, prevDumpDir)
1659			}
1660			// Check against the current version.
1661			sourceDump = implDump
1662			if isLlndk && currVendorVersion != "" {
1663				currVersion = currVendorVersion
1664				if android.IsTrunkStableVendorApiLevel(currVersion) {
1665					sourceDump = llndkDump
1666				}
1667			} else {
1668				currVersion = currSdkVersion
1669				if isApex && (!ctx.Config().PlatformSdkFinal() ||
1670					ctx.Config().PlatformSdkVersion().FinalInt() > 34) {
1671					sourceDump = apexVariantDump
1672				}
1673			}
1674			currDumpDir := filepath.Join(dumpDir, currVersion, binderBitness)
1675			currDumpFile := getRefAbiDumpFile(ctx, currDumpDir, fileName)
1676			if currDumpFile.Valid() {
1677				library.sameVersionAbiDiff(ctx, sourceDump, currDumpFile.Path(),
1678					fileName, nameExt, isLlndk, string(tag))
1679			}
1680		}
1681
1682		// Assert that a module is tagged with at most one of platformLsdumpTag, productLsdumpTag, or vendorLsdumpTag.
1683		if len(headerAbiChecker.Ref_dump_dirs) > 0 && len(optInTags) != 1 {
1684			ctx.ModuleErrorf("Expect exactly one opt-in lsdump tag when ref_dump_dirs are specified: %s", optInTags)
1685			return
1686		}
1687		// Ensure that a module tagged with only platformLsdumpTag has ref_dump_dirs.
1688		// Android.bp in vendor projects should be cleaned up before this is enforced for vendorLsdumpTag and productLsdumpTag.
1689		if len(headerAbiChecker.Ref_dump_dirs) == 0 && len(tags) == 1 && tags[0] == platformLsdumpTag {
1690			ctx.ModuleErrorf("header_abi_checker is explicitly enabled, but no ref_dump_dirs are specified.")
1691		}
1692		// Check against the opt-in reference dumps.
1693		for i, optInDumpDir := range headerAbiChecker.Ref_dump_dirs {
1694			optInDumpDirPath := android.PathForModuleSrc(ctx, optInDumpDir)
1695			// Ref_dump_dirs are not versioned.
1696			// They do not contain subdir for binder bitness because 64-bit binder has been mandatory.
1697			optInDumpFile := getRefAbiDumpFile(ctx, optInDumpDirPath.String(), fileName)
1698			if !optInDumpFile.Valid() {
1699				continue
1700			}
1701			library.optInAbiDiff(ctx,
1702				implDump, optInDumpFile.Path(),
1703				fileName, "opt"+strconv.Itoa(i), optInDumpDirPath.String(), string(optInTags[0]))
1704		}
1705	}
1706}
1707
1708// link registers actions to link this library, and sets various fields
1709// on this library to reflect information that should be exported up the build
1710// tree (for example, exported flags and include paths).
1711func (library *libraryDecorator) link(ctx ModuleContext,
1712	flags Flags, deps PathDeps, objs Objects) android.Path {
1713
1714	if ctx.IsLlndk() {
1715		// override the module's export_include_dirs with llndk.override_export_include_dirs
1716		// if it is set.
1717		if override := library.Properties.Llndk.Override_export_include_dirs; override != nil {
1718			library.flagExporter.Properties.Export_include_dirs = proptools.NewConfigurable[[]string](
1719				nil,
1720				[]proptools.ConfigurableCase[[]string]{
1721					proptools.NewConfigurableCase[[]string](nil, &override),
1722				},
1723			)
1724		}
1725
1726		if Bool(library.Properties.Llndk.Export_headers_as_system) {
1727			library.flagExporter.Properties.Export_system_include_dirs = append(
1728				library.flagExporter.Properties.Export_system_include_dirs,
1729				library.flagExporter.Properties.Export_include_dirs.GetOrDefault(ctx, nil)...)
1730			library.flagExporter.Properties.Export_include_dirs = proptools.NewConfigurable[[]string](nil, nil)
1731		}
1732	}
1733
1734	if ctx.IsVendorPublicLibrary() {
1735		// override the module's export_include_dirs with vendor_public_library.override_export_include_dirs
1736		// if it is set.
1737		if override := library.Properties.Vendor_public_library.Override_export_include_dirs; override != nil {
1738			library.flagExporter.Properties.Export_include_dirs = proptools.NewConfigurable[[]string](
1739				nil,
1740				[]proptools.ConfigurableCase[[]string]{
1741					proptools.NewConfigurableCase[[]string](nil, &override),
1742				},
1743			)
1744		}
1745	}
1746
1747	// Linking this library consists of linking `deps.Objs` (.o files in dependencies
1748	// of this library), together with `objs` (.o files created by compiling this
1749	// library).
1750	objs = deps.Objs.Copy().Append(objs)
1751	var out android.Path
1752	if library.static() || library.header() {
1753		out = library.linkStatic(ctx, flags, deps, objs)
1754	} else {
1755		out = library.linkShared(ctx, flags, deps, objs)
1756	}
1757
1758	// Export include paths and flags to be propagated up the tree.
1759	library.exportIncludes(ctx)
1760	library.reexportDirs(deps.ReexportedDirs...)
1761	library.reexportSystemDirs(deps.ReexportedSystemDirs...)
1762	library.reexportFlags(deps.ReexportedFlags...)
1763	library.reexportDeps(deps.ReexportedDeps...)
1764	library.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
1765
1766	if library.static() && len(deps.ReexportedRustRlibDeps) > 0 {
1767		library.reexportRustStaticDeps(deps.ReexportedRustRlibDeps...)
1768	}
1769
1770	// Optionally export aidl headers.
1771	if Bool(library.Properties.Aidl.Export_aidl_headers) {
1772		if library.baseCompiler.hasAidl(ctx, deps) {
1773			if library.baseCompiler.hasSrcExt(ctx, ".aidl") {
1774				dir := android.PathForModuleGen(ctx, "aidl")
1775				library.reexportDirs(dir)
1776			}
1777			if len(deps.AidlLibraryInfos) > 0 {
1778				dir := android.PathForModuleGen(ctx, "aidl_library")
1779				library.reexportDirs(dir)
1780			}
1781
1782			library.reexportDeps(library.baseCompiler.aidlOrderOnlyDeps...)
1783			library.addExportedGeneratedHeaders(library.baseCompiler.aidlHeaders...)
1784		}
1785	}
1786
1787	// Optionally export proto headers.
1788	if Bool(library.Properties.Proto.Export_proto_headers) {
1789		if library.baseCompiler.hasSrcExt(ctx, ".proto") {
1790			var includes android.Paths
1791			if flags.proto.CanonicalPathFromRoot {
1792				includes = append(includes, flags.proto.SubDir)
1793			}
1794			includes = append(includes, flags.proto.Dir)
1795			library.reexportDirs(includes...)
1796
1797			library.reexportDeps(library.baseCompiler.protoOrderOnlyDeps...)
1798			library.addExportedGeneratedHeaders(library.baseCompiler.protoHeaders...)
1799		}
1800	}
1801
1802	// If the library is sysprop_library, expose either public or internal header selectively.
1803	if library.baseCompiler.hasSrcExt(ctx, ".sysprop") {
1804		dir := android.PathForModuleGen(ctx, "sysprop", "include")
1805		if library.Properties.Sysprop.Platform != nil {
1806			isOwnerPlatform := Bool(library.Properties.Sysprop.Platform)
1807
1808			// If the owner is different from the user, expose public header. That is,
1809			// 1) if the user is product (as owner can only be platform / vendor)
1810			// 2) if the owner is platform and the client is vendor
1811			// We don't care Platform -> Vendor dependency as it's already forbidden.
1812			if ctx.Device() && (ctx.ProductSpecific() || (isOwnerPlatform && ctx.inVendor())) {
1813				dir = android.PathForModuleGen(ctx, "sysprop/public", "include")
1814			}
1815		}
1816
1817		// Make sure to only export headers which are within the include directory.
1818		_, headers := android.FilterPathListPredicate(library.baseCompiler.syspropHeaders, func(path android.Path) bool {
1819			_, isRel := android.MaybeRel(ctx, dir.String(), path.String())
1820			return isRel
1821		})
1822
1823		// Add sysprop-related directories to the exported directories of this library.
1824		library.reexportDirs(dir)
1825		library.reexportDeps(library.baseCompiler.syspropOrderOnlyDeps...)
1826		library.addExportedGeneratedHeaders(headers...)
1827	}
1828
1829	// Add stub-related flags if this library is a stub library.
1830	library.exportVersioningMacroIfNeeded(ctx)
1831
1832	// Propagate a Provider containing information about exported flags, deps, and include paths.
1833	library.flagExporter.setProvider(ctx)
1834
1835	return out
1836}
1837
1838func (library *libraryDecorator) exportVersioningMacroIfNeeded(ctx android.BaseModuleContext) {
1839	if library.BuildStubs() && library.StubsVersion() != "" && !library.skipAPIDefine {
1840		name := versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx))
1841		apiLevel, err := android.ApiLevelFromUser(ctx, library.StubsVersion())
1842		if err != nil {
1843			ctx.ModuleErrorf("Can't export version macro: %s", err.Error())
1844		}
1845		library.reexportFlags("-D" + name + "=" + strconv.Itoa(apiLevel.FinalOrPreviewInt()))
1846	}
1847}
1848
1849// buildStatic returns true if this library should be built as a static library.
1850func (library *libraryDecorator) buildStatic() bool {
1851	return library.MutatedProperties.BuildStatic &&
1852		BoolDefault(library.StaticProperties.Static.Enabled, true)
1853}
1854
1855// buildShared returns true if this library should be built as a shared library.
1856func (library *libraryDecorator) buildShared() bool {
1857	return library.MutatedProperties.BuildShared &&
1858		BoolDefault(library.SharedProperties.Shared.Enabled, true)
1859}
1860
1861func (library *libraryDecorator) objs() Objects {
1862	return library.objects
1863}
1864
1865func (library *libraryDecorator) reuseObjs() Objects {
1866	return library.reuseObjects
1867}
1868
1869func (library *libraryDecorator) toc() android.OptionalPath {
1870	return library.tocFile
1871}
1872
1873func (library *libraryDecorator) installSymlinkToRuntimeApex(ctx ModuleContext, file android.Path) {
1874	dir := library.baseInstaller.installDir(ctx)
1875	dirOnDevice := android.InstallPathToOnDevicePath(ctx, dir)
1876	// libc_hwasan has relative_install_dir set, which would mess up the dir.Base() logic.
1877	// hardcode here because it's the only target, if we have other targets that use this
1878	// we can generalise this.
1879	var target string
1880	if ctx.baseModuleName() == "libc_hwasan" {
1881		target = "/" + filepath.Join("apex", "com.android.runtime", "lib64", "bionic", "hwasan", file.Base())
1882	} else {
1883		base := dir.Base()
1884		target = "/" + filepath.Join("apex", "com.android.runtime", base, "bionic", file.Base())
1885	}
1886	ctx.InstallAbsoluteSymlink(dir, file.Base(), target)
1887	library.postInstallCmds = append(library.postInstallCmds, makeSymlinkCmd(dirOnDevice, file.Base(), target))
1888}
1889
1890func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
1891	if library.shared() {
1892		translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
1893		if library.HasStubsVariants() && !ctx.Host() && !ctx.isSdkVariant() &&
1894			InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.BuildStubs() &&
1895			!translatedArch && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() {
1896			// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
1897			// The original path becomes a symlink to the corresponding file in the
1898			// runtime APEX.
1899			if ctx.Device() {
1900				library.installSymlinkToRuntimeApex(ctx, file)
1901			}
1902			library.baseInstaller.subDir = "bootstrap"
1903		}
1904
1905		library.baseInstaller.install(ctx, file)
1906	}
1907
1908	if Bool(library.Properties.Static_ndk_lib) && library.static() &&
1909		!ctx.InVendorOrProduct() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
1910		library.baseLinker.sanitize.isUnsanitizedVariant() &&
1911		CtxIsForPlatform(ctx) && !ctx.isPreventInstall() {
1912		installPath := getUnversionedLibraryInstallPath(ctx).Join(ctx, file.Base())
1913
1914		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
1915			Rule:        android.Cp,
1916			Description: "install " + installPath.Base(),
1917			Output:      installPath,
1918			Input:       file,
1919		})
1920
1921		library.ndkSysrootPath = installPath
1922	}
1923}
1924
1925func (library *libraryDecorator) everInstallable() bool {
1926	// Only shared and static libraries are installed. Header libraries (which are
1927	// neither static or shared) are not installed.
1928	return library.shared() || library.static()
1929}
1930
1931// static returns true if this library is for a "static" variant.
1932func (library *libraryDecorator) static() bool {
1933	return library.MutatedProperties.VariantIsStatic
1934}
1935
1936// staticLibrary returns true if this library is for a "static"" variant.
1937func (library *libraryDecorator) staticLibrary() bool {
1938	return library.static()
1939}
1940
1941// shared returns true if this library is for a "shared" variant.
1942func (library *libraryDecorator) shared() bool {
1943	return library.MutatedProperties.VariantIsShared
1944}
1945
1946// header returns true if this library is for a header-only variant.
1947func (library *libraryDecorator) header() bool {
1948	// Neither "static" nor "shared" implies this library is header-only.
1949	return !library.static() && !library.shared()
1950}
1951
1952// setStatic marks the library variant as "static".
1953func (library *libraryDecorator) setStatic() {
1954	library.MutatedProperties.VariantIsStatic = true
1955	library.MutatedProperties.VariantIsShared = false
1956}
1957
1958// setShared marks the library variant as "shared".
1959func (library *libraryDecorator) setShared() {
1960	library.MutatedProperties.VariantIsStatic = false
1961	library.MutatedProperties.VariantIsShared = true
1962}
1963
1964// BuildOnlyStatic disables building this library as a shared library.
1965func (library *libraryDecorator) BuildOnlyStatic() {
1966	library.MutatedProperties.BuildShared = false
1967}
1968
1969// BuildOnlyShared disables building this library as a static library.
1970func (library *libraryDecorator) BuildOnlyShared() {
1971	library.MutatedProperties.BuildStatic = false
1972}
1973
1974// HeaderOnly disables building this library as a shared or static library;
1975// the library only exists to propagate header file dependencies up the build graph.
1976func (library *libraryDecorator) HeaderOnly() {
1977	library.MutatedProperties.BuildShared = false
1978	library.MutatedProperties.BuildStatic = false
1979}
1980
1981// HasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
1982func (library *libraryDecorator) HasLLNDKStubs() bool {
1983	return String(library.Properties.Llndk.Symbol_file) != ""
1984}
1985
1986// hasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
1987func (library *libraryDecorator) HasLLNDKHeaders() bool {
1988	return Bool(library.Properties.Llndk.Llndk_headers)
1989}
1990
1991// IsLLNDKMovedToApex returns true if this cc_library module sets the llndk.moved_to_apex property.
1992func (library *libraryDecorator) IsLLNDKMovedToApex() bool {
1993	return Bool(library.Properties.Llndk.Moved_to_apex)
1994}
1995
1996// HasVendorPublicLibrary returns true if this cc_library module has a variant that will build
1997// vendor public library stubs.
1998func (library *libraryDecorator) HasVendorPublicLibrary() bool {
1999	return String(library.Properties.Vendor_public_library.Symbol_file) != ""
2000}
2001
2002func (library *libraryDecorator) ImplementationModuleName(name string) string {
2003	return name
2004}
2005
2006func (library *libraryDecorator) BuildStubs() bool {
2007	return library.MutatedProperties.BuildStubs
2008}
2009
2010func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *string {
2011	if props := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module)); props.Symbol_file != nil {
2012		return props.Symbol_file
2013	}
2014	if library.HasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
2015		return library.Properties.Stubs.Symbol_file
2016	}
2017	// TODO(b/309880485): Distinguish platform, NDK, LLNDK, and APEX version scripts.
2018	if library.baseLinker.Properties.Version_script != nil {
2019		return library.baseLinker.Properties.Version_script
2020	}
2021	return nil
2022}
2023
2024func (library *libraryDecorator) HasStubsVariants() bool {
2025	// Just having stubs.symbol_file is enough to create a stub variant. In that case
2026	// the stub for the future API level is created.
2027	return library.Properties.Stubs.Symbol_file != nil ||
2028		len(library.Properties.Stubs.Versions) > 0
2029}
2030
2031func (library *libraryDecorator) IsStubsImplementationRequired() bool {
2032	return BoolDefault(library.Properties.Stubs.Implementation_installable, true)
2033}
2034
2035func (library *libraryDecorator) StubsVersions(ctx android.BaseModuleContext) []string {
2036	if !library.HasStubsVariants() {
2037		return nil
2038	}
2039
2040	if library.HasLLNDKStubs() && ctx.Module().(*Module).InVendorOrProduct() {
2041		// LLNDK libraries only need a single stubs variant (""), which is
2042		// added automatically in createVersionVariations().
2043		return nil
2044	}
2045
2046	// Future API level is implicitly added if there isn't
2047	versions := AddCurrentVersionIfNotPresent(library.Properties.Stubs.Versions)
2048	NormalizeVersions(ctx, versions)
2049	return versions
2050}
2051
2052func AddCurrentVersionIfNotPresent(vers []string) []string {
2053	if inList(android.FutureApiLevel.String(), vers) {
2054		return vers
2055	}
2056	// In some cases, people use the raw value "10000" in the versions property.
2057	// We shouldn't add the future API level in that case, otherwise there will
2058	// be two identical versions.
2059	if inList(strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt()), vers) {
2060		return vers
2061	}
2062	return append(vers, android.FutureApiLevel.String())
2063}
2064
2065func (library *libraryDecorator) SetStubsVersion(version string) {
2066	library.MutatedProperties.StubsVersion = version
2067}
2068
2069func (library *libraryDecorator) StubsVersion() string {
2070	return library.MutatedProperties.StubsVersion
2071}
2072
2073func (library *libraryDecorator) SetBuildStubs(isLatest bool) {
2074	library.MutatedProperties.BuildStubs = true
2075	library.MutatedProperties.IsLatestVersion = isLatest
2076}
2077
2078func (library *libraryDecorator) SetAllStubsVersions(versions []string) {
2079	library.MutatedProperties.AllStubsVersions = versions
2080}
2081
2082func (library *libraryDecorator) AllStubsVersions() []string {
2083	return library.MutatedProperties.AllStubsVersions
2084}
2085
2086func (library *libraryDecorator) isLatestStubVersion() bool {
2087	return library.MutatedProperties.IsLatestVersion
2088}
2089
2090func (library *libraryDecorator) apexAvailable() []string {
2091	var list []string
2092	if library.static() {
2093		list = library.StaticProperties.Static.Apex_available
2094	} else if library.shared() {
2095		list = library.SharedProperties.Shared.Apex_available
2096	}
2097
2098	return list
2099}
2100
2101func (library *libraryDecorator) installable() *bool {
2102	if library.static() {
2103		return library.StaticProperties.Static.Installable
2104	} else if library.shared() {
2105		return library.SharedProperties.Shared.Installable
2106	}
2107	return nil
2108}
2109
2110func (library *libraryDecorator) makeUninstallable(mod *Module) {
2111	if library.static() && library.buildStatic() && !library.BuildStubs() {
2112		// If we're asked to make a static library uninstallable we don't do
2113		// anything since AndroidMkEntries always sets LOCAL_UNINSTALLABLE_MODULE
2114		// for these entries. This is done to still get the make targets for NOTICE
2115		// files from notice_files.mk, which other libraries might depend on.
2116		return
2117	}
2118	mod.ModuleBase.MakeUninstallable()
2119}
2120
2121func (library *libraryDecorator) getPartition() string {
2122	return library.path.Partition()
2123}
2124
2125func (library *libraryDecorator) GetAPIListCoverageXMLPath() android.ModuleOutPath {
2126	return library.apiListCoverageXmlPath
2127}
2128
2129func (library *libraryDecorator) setAPIListCoverageXMLPath(xml android.ModuleOutPath) {
2130	library.apiListCoverageXmlPath = xml
2131}
2132
2133func (library *libraryDecorator) overriddenModules() []string {
2134	return library.Properties.Overrides
2135}
2136
2137func (library *libraryDecorator) defaultDistFiles() []android.Path {
2138	if library.defaultDistFile == nil {
2139		return nil
2140	}
2141	return []android.Path{library.defaultDistFile}
2142}
2143
2144var _ overridable = (*libraryDecorator)(nil)
2145
2146var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
2147
2148// versioningMacroNamesList returns a singleton map, where keys are "version macro names",
2149// and values are the module name responsible for registering the version macro name.
2150//
2151// Version macros are used when building against stubs, to provide version information about
2152// the stub. Only stub libraries should have an entry in this list.
2153//
2154// For example, when building against libFoo#ver, __LIBFOO_API__ macro is set to ver so
2155// that headers from libFoo can be conditionally compiled (this may hide APIs
2156// that are not available for the version).
2157//
2158// This map is used to ensure that there aren't conflicts between these version macro names.
2159func versioningMacroNamesList(config android.Config) *map[string]string {
2160	return config.Once(versioningMacroNamesListKey, func() interface{} {
2161		m := make(map[string]string)
2162		return &m
2163	}).(*map[string]string)
2164}
2165
2166// alphanumeric and _ characters are preserved.
2167// other characters are all converted to _
2168var charsNotForMacro = regexp.MustCompile("[^a-zA-Z0-9_]+")
2169
2170// versioningMacroName returns the canonical version macro name for the given module.
2171func versioningMacroName(moduleName string) string {
2172	macroName := charsNotForMacro.ReplaceAllString(moduleName, "_")
2173	macroName = strings.ToUpper(macroName)
2174	return "__" + macroName + "_API__"
2175}
2176
2177// NewLibrary builds and returns a new Module corresponding to a C++ library.
2178// Individual module implementations which comprise a C++ library (or something like
2179// a C++ library) should call this function, set some fields on the result, and
2180// then call the Init function.
2181func NewLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
2182	module := newModule(hod, android.MultilibBoth)
2183
2184	library := &libraryDecorator{
2185		MutatedProperties: LibraryMutatedProperties{
2186			BuildShared: true,
2187			BuildStatic: true,
2188		},
2189		baseCompiler:  NewBaseCompiler(),
2190		baseLinker:    NewBaseLinker(module.sanitize),
2191		baseInstaller: NewBaseInstaller("lib", "lib64", InstallInSystem),
2192		sabi:          module.sabi,
2193	}
2194
2195	module.compiler = library
2196	module.linker = library
2197	module.installer = library
2198	module.library = library
2199
2200	return module, library
2201}
2202
2203// connects a shared library to a static library in order to reuse its .o files to avoid
2204// compiling source files twice.
2205func reuseStaticLibrary(ctx android.BottomUpMutatorContext, shared *Module) {
2206	if sharedCompiler, ok := shared.compiler.(*libraryDecorator); ok {
2207
2208		// Check libraries in addition to cflags, since libraries may be exporting different
2209		// include directories.
2210		if len(sharedCompiler.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)) == 0 &&
2211			len(sharedCompiler.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)) == 0 &&
2212			len(sharedCompiler.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 &&
2213			len(sharedCompiler.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 &&
2214			len(sharedCompiler.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)) == 0 &&
2215			len(sharedCompiler.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)) == 0 &&
2216			len(sharedCompiler.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)) == 0 &&
2217			len(sharedCompiler.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)) == 0 &&
2218			// Compare System_shared_libs properties with nil because empty lists are
2219			// semantically significant for them.
2220			sharedCompiler.StaticProperties.Static.System_shared_libs == nil &&
2221			sharedCompiler.SharedProperties.Shared.System_shared_libs == nil {
2222
2223			ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, reuseObjTag, ctx.ModuleName())
2224		}
2225
2226		// This dep is just to reference static variant from shared variant
2227		ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, staticVariantTag, ctx.ModuleName())
2228	}
2229}
2230
2231// linkageTransitionMutator adds "static" or "shared" variants for modules depending
2232// on whether the module can be built as a static library or a shared library.
2233type linkageTransitionMutator struct{}
2234
2235func (linkageTransitionMutator) Split(ctx android.BaseModuleContext) []string {
2236	ccPrebuilt := false
2237	if m, ok := ctx.Module().(*Module); ok && m.linker != nil {
2238		_, ccPrebuilt = m.linker.(prebuiltLibraryInterface)
2239	}
2240	if ccPrebuilt {
2241		library := ctx.Module().(*Module).linker.(prebuiltLibraryInterface)
2242
2243		// Differentiate between header only and building an actual static/shared library
2244		buildStatic := library.buildStatic()
2245		buildShared := library.buildShared()
2246		if buildStatic || buildShared {
2247			// Always create both the static and shared variants for prebuilt libraries, and then disable the one
2248			// that is not being used.  This allows them to share the name of a cc_library module, which requires that
2249			// all the variants of the cc_library also exist on the prebuilt.
2250			return []string{"static", "shared"}
2251		} else {
2252			// Header only
2253		}
2254	} else if library, ok := ctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface()) {
2255		// Non-cc.Modules may need an empty variant for their mutators.
2256		variations := []string{}
2257		if library.NonCcVariants() {
2258			variations = append(variations, "")
2259		}
2260		isLLNDK := false
2261		if m, ok := ctx.Module().(*Module); ok {
2262			isLLNDK = m.IsLlndk()
2263		}
2264		buildStatic := library.BuildStaticVariant() && !isLLNDK
2265		buildShared := library.BuildSharedVariant()
2266		if buildStatic && buildShared {
2267			variations = append([]string{"static", "shared"}, variations...)
2268			return variations
2269		} else if buildStatic {
2270			variations = append([]string{"static"}, variations...)
2271		} else if buildShared {
2272			variations = append([]string{"shared"}, variations...)
2273		}
2274
2275		if len(variations) > 0 {
2276			return variations
2277		}
2278	}
2279	return []string{""}
2280}
2281
2282func (linkageTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
2283	if ctx.DepTag() == android.PrebuiltDepTag {
2284		return sourceVariation
2285	}
2286	return ""
2287}
2288
2289func (linkageTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
2290	ccPrebuilt := false
2291	if m, ok := ctx.Module().(*Module); ok && m.linker != nil {
2292		_, ccPrebuilt = m.linker.(prebuiltLibraryInterface)
2293	}
2294	if ccPrebuilt {
2295		if incomingVariation != "" {
2296			return incomingVariation
2297		}
2298		library := ctx.Module().(*Module).linker.(prebuiltLibraryInterface)
2299		if library.buildShared() {
2300			return "shared"
2301		} else if library.buildStatic() {
2302			return "static"
2303		}
2304		return ""
2305	} else if library, ok := ctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() {
2306		isLLNDK := false
2307		if m, ok := ctx.Module().(*Module); ok {
2308			isLLNDK = m.IsLlndk()
2309		}
2310		buildStatic := library.BuildStaticVariant() && !isLLNDK
2311		buildShared := library.BuildSharedVariant()
2312		if library.BuildRlibVariant() && !buildStatic && (incomingVariation == "static" || incomingVariation == "") {
2313			// Rust modules do not build static libs, but rlibs are used as if they
2314			// were via `static_libs`. Thus we need to alias the BuildRlibVariant
2315			// to "static" for Rust FFI libraries.
2316			return ""
2317		}
2318		if incomingVariation != "" {
2319			return incomingVariation
2320		}
2321		if buildShared {
2322			return "shared"
2323		} else if buildStatic {
2324			return "static"
2325		}
2326		return ""
2327	}
2328	return ""
2329}
2330
2331func (linkageTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
2332	ccPrebuilt := false
2333	if m, ok := ctx.Module().(*Module); ok && m.linker != nil {
2334		_, ccPrebuilt = m.linker.(prebuiltLibraryInterface)
2335	}
2336	if ccPrebuilt {
2337		library := ctx.Module().(*Module).linker.(prebuiltLibraryInterface)
2338		if variation == "static" {
2339			library.setStatic()
2340			if !library.buildStatic() {
2341				library.disablePrebuilt()
2342				ctx.Module().(*Module).Prebuilt().SetUsePrebuilt(false)
2343			}
2344		} else if variation == "shared" {
2345			library.setShared()
2346			if !library.buildShared() {
2347				library.disablePrebuilt()
2348				ctx.Module().(*Module).Prebuilt().SetUsePrebuilt(false)
2349			}
2350		}
2351	} else if library, ok := ctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() {
2352		if variation == "static" {
2353			library.SetStatic()
2354		} else if variation == "shared" {
2355			library.SetShared()
2356			var isLLNDK bool
2357			if m, ok := ctx.Module().(*Module); ok {
2358				isLLNDK = m.IsLlndk()
2359			}
2360			buildStatic := library.BuildStaticVariant() && !isLLNDK
2361			buildShared := library.BuildSharedVariant()
2362			if buildStatic && buildShared {
2363				if _, ok := library.(*Module); ok {
2364					reuseStaticLibrary(ctx, library.(*Module))
2365				}
2366			}
2367		}
2368	}
2369}
2370
2371// NormalizeVersions modifies `versions` in place, so that each raw version
2372// string becomes its normalized canonical form.
2373// Validates that the versions in `versions` are specified in least to greatest order.
2374func NormalizeVersions(ctx android.BaseModuleContext, versions []string) {
2375	var previous android.ApiLevel
2376	for i, v := range versions {
2377		ver, err := android.ApiLevelFromUser(ctx, v)
2378		if err != nil {
2379			ctx.PropertyErrorf("versions", "%s", err.Error())
2380			return
2381		}
2382		if i > 0 && ver.LessThanOrEqualTo(previous) {
2383			ctx.PropertyErrorf("versions", "not sorted: %v", versions)
2384		}
2385		versions[i] = ver.String()
2386		previous = ver
2387	}
2388}
2389
2390func perApiVersionVariations(mctx android.BaseModuleContext, minSdkVersion string) []string {
2391	from, err := NativeApiLevelFromUser(mctx, minSdkVersion)
2392	if err != nil {
2393		mctx.PropertyErrorf("min_sdk_version", err.Error())
2394		return []string{""}
2395	}
2396
2397	return ndkLibraryVersions(mctx, from)
2398}
2399
2400func canBeOrLinkAgainstVersionVariants(module interface {
2401	Host() bool
2402	InRamdisk() bool
2403	InVendorRamdisk() bool
2404}) bool {
2405	return !module.Host() && !module.InRamdisk() && !module.InVendorRamdisk()
2406}
2407
2408func canBeVersionVariant(module interface {
2409	Host() bool
2410	InRamdisk() bool
2411	InVendorRamdisk() bool
2412	CcLibraryInterface() bool
2413	Shared() bool
2414}) bool {
2415	return canBeOrLinkAgainstVersionVariants(module) &&
2416		module.CcLibraryInterface() && module.Shared()
2417}
2418
2419func moduleVersionedInterface(module blueprint.Module) VersionedInterface {
2420	if m, ok := module.(VersionedLinkableInterface); ok {
2421		return m.VersionedInterface()
2422	}
2423	return nil
2424}
2425
2426// setStubsVersions normalizes the versions in the Stubs.Versions property into MutatedProperties.AllStubsVersions.
2427func setStubsVersions(mctx android.BaseModuleContext, module VersionedLinkableInterface) {
2428	if !module.BuildSharedVariant() || !canBeVersionVariant(module) {
2429		return
2430	}
2431	versions := module.VersionedInterface().StubsVersions(mctx)
2432	if mctx.Failed() {
2433		return
2434	}
2435	// Set the versions on the pre-mutated module so they can be read by any llndk modules that
2436	// depend on the implementation library and haven't been mutated yet.
2437	module.VersionedInterface().SetAllStubsVersions(versions)
2438}
2439
2440// versionTransitionMutator splits a module into the mandatory non-stubs variant
2441// (which is unnamed) and zero or more stubs variants.
2442type versionTransitionMutator struct{}
2443
2444func (versionTransitionMutator) Split(ctx android.BaseModuleContext) []string {
2445	if ctx.Os() != android.Android {
2446		return []string{""}
2447	}
2448	if m, ok := ctx.Module().(VersionedLinkableInterface); ok {
2449		if m.CcLibraryInterface() && canBeVersionVariant(m) {
2450			setStubsVersions(ctx, m)
2451			return append(slices.Clone(m.VersionedInterface().AllStubsVersions()), "")
2452		} else if m.SplitPerApiLevel() && m.IsSdkVariant() {
2453			return perApiVersionVariations(ctx, m.MinSdkVersion())
2454		}
2455	}
2456
2457	return []string{""}
2458}
2459
2460func (versionTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
2461	if ctx.DepTag() == android.PrebuiltDepTag {
2462		return sourceVariation
2463	}
2464	return ""
2465}
2466
2467func (versionTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
2468	if ctx.Os() != android.Android {
2469		return ""
2470	}
2471	m, ok := ctx.Module().(VersionedLinkableInterface)
2472	if library := moduleVersionedInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
2473		if incomingVariation == "latest" {
2474			latestVersion := ""
2475			versions := library.AllStubsVersions()
2476			if len(versions) > 0 {
2477				latestVersion = versions[len(versions)-1]
2478			}
2479			return latestVersion
2480		}
2481		return incomingVariation
2482	} else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() {
2483		// If this module only has variants with versions and the incoming dependency doesn't specify which one
2484		// is needed then assume the latest version.
2485		if incomingVariation == "" {
2486			return android.FutureApiLevel.String()
2487		}
2488		return incomingVariation
2489	}
2490
2491	return ""
2492}
2493
2494func (versionTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
2495	// Optimization: return early if this module can't be affected.
2496	if ctx.Os() != android.Android {
2497		return
2498	}
2499
2500	m, ok := ctx.Module().(VersionedLinkableInterface)
2501	if library := moduleVersionedInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
2502		isLLNDK := m.IsLlndk()
2503		isVendorPublicLibrary := m.IsVendorPublicLibrary()
2504
2505		if variation != "" || isLLNDK || isVendorPublicLibrary {
2506			// A stubs or LLNDK stubs variant.
2507			if sm, ok := ctx.Module().(PlatformSanitizeable); ok && sm.SanitizePropDefined() {
2508				sm.ForceDisableSanitizers()
2509			}
2510			m.SetStl("none")
2511			m.SetPreventInstall()
2512			allStubsVersions := m.VersionedInterface().AllStubsVersions()
2513			isLatest := len(allStubsVersions) > 0 && variation == allStubsVersions[len(allStubsVersions)-1]
2514			m.VersionedInterface().SetBuildStubs(isLatest)
2515		}
2516		if variation != "" {
2517			// A non-LLNDK stubs module is hidden from make
2518			m.VersionedInterface().SetStubsVersion(variation)
2519			m.SetHideFromMake()
2520		} else {
2521			// A non-LLNDK implementation module has a dependency to all stubs versions
2522			for _, version := range m.VersionedInterface().AllStubsVersions() {
2523				ctx.AddVariationDependencies(
2524					[]blueprint.Variation{
2525						{Mutator: "version", Variation: version},
2526						{Mutator: "link", Variation: "shared"}},
2527					StubImplDepTag, ctx.ModuleName())
2528			}
2529		}
2530	} else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() {
2531		m.SetSdkVersion(variation)
2532		m.SetMinSdkVersion(variation)
2533	}
2534}
2535
2536// maybeInjectBoringSSLHash adds a rule to run bssl_inject_hash on the output file if the module has the
2537// inject_bssl_hash or if any static library dependencies have inject_bssl_hash set.  It returns the output path
2538// that the linked output file should be written to.
2539// TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries.
2540func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.ModuleOutPath,
2541	inject *bool, fileName string) android.ModuleOutPath {
2542	// TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries.
2543	injectBoringSSLHash := Bool(inject)
2544	ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
2545		if tag, ok := ctx.OtherModuleDependencyTag(dep).(libraryDependencyTag); ok && tag.static() {
2546			if ccInfo, ok := android.OtherModuleProvider(ctx, dep, CcInfoProvider); ok &&
2547				ccInfo.LinkerInfo != nil && ccInfo.LinkerInfo.LibraryDecoratorInfo != nil {
2548				if ccInfo.LinkerInfo.LibraryDecoratorInfo.InjectBsslHash {
2549					injectBoringSSLHash = true
2550				}
2551			}
2552		}
2553	})
2554	if injectBoringSSLHash {
2555		hashedOutputfile := outputFile
2556		outputFile = android.PathForModuleOut(ctx, "unhashed", fileName)
2557
2558		rule := android.NewRuleBuilder(pctx, ctx)
2559		rule.Command().
2560			BuiltTool("bssl_inject_hash").
2561			FlagWithInput("-in-object ", outputFile).
2562			FlagWithOutput("-o ", hashedOutputfile)
2563		rule.Build("injectCryptoHash", "inject crypto hash")
2564	}
2565
2566	return outputFile
2567}
2568