1// Copyright 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package rust
16
17import (
18	"fmt"
19	"strings"
20
21	"android/soong/bloaty"
22	"android/soong/testing"
23
24	"github.com/google/blueprint"
25	"github.com/google/blueprint/proptools"
26
27	"android/soong/android"
28	"android/soong/cc"
29	cc_config "android/soong/cc/config"
30	"android/soong/fuzz"
31	"android/soong/multitree"
32	"android/soong/rust/config"
33)
34
35var pctx = android.NewPackageContext("android/soong/rust")
36
37func init() {
38	android.RegisterModuleType("rust_defaults", defaultsFactory)
39	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
40		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
41		ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel()
42		ctx.BottomUp("rust_begin", BeginMutator).Parallel()
43	})
44	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
45		ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
46	})
47	pctx.Import("android/soong/android")
48	pctx.Import("android/soong/rust/config")
49	pctx.ImportAs("cc_config", "android/soong/cc/config")
50	android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory)
51}
52
53type Flags struct {
54	GlobalRustFlags []string // Flags that apply globally to rust
55	GlobalLinkFlags []string // Flags that apply globally to linker
56	RustFlags       []string // Flags that apply to rust
57	LinkFlags       []string // Flags that apply to linker
58	ClippyFlags     []string // Flags that apply to clippy-driver, during the linting
59	RustdocFlags    []string // Flags that apply to rustdoc
60	Toolchain       config.Toolchain
61	Coverage        bool
62	Clippy          bool
63	EmitXrefs       bool // If true, emit rules to aid cross-referencing
64}
65
66type BaseProperties struct {
67	AndroidMkRlibs         []string `blueprint:"mutated"`
68	AndroidMkDylibs        []string `blueprint:"mutated"`
69	AndroidMkProcMacroLibs []string `blueprint:"mutated"`
70	AndroidMkStaticLibs    []string `blueprint:"mutated"`
71	AndroidMkHeaderLibs    []string `blueprint:"mutated"`
72
73	ImageVariation string `blueprint:"mutated"`
74	VndkVersion    string `blueprint:"mutated"`
75	SubName        string `blueprint:"mutated"`
76
77	// SubName is used by CC for tracking image variants / SDK versions. RustSubName is used for Rust-specific
78	// subnaming which shouldn't be visible to CC modules (such as the rlib stdlinkage subname). This should be
79	// appended before SubName.
80	RustSubName string `blueprint:"mutated"`
81
82	// Set by imageMutator
83	CoreVariantNeeded          bool     `blueprint:"mutated"`
84	VendorRamdiskVariantNeeded bool     `blueprint:"mutated"`
85	RamdiskVariantNeeded       bool     `blueprint:"mutated"`
86	RecoveryVariantNeeded      bool     `blueprint:"mutated"`
87	ExtraVariants              []string `blueprint:"mutated"`
88
89	// Allows this module to use non-APEX version of libraries. Useful
90	// for building binaries that are started before APEXes are activated.
91	Bootstrap *bool
92
93	// Used by vendor snapshot to record dependencies from snapshot modules.
94	SnapshotSharedLibs []string `blueprint:"mutated"`
95	SnapshotStaticLibs []string `blueprint:"mutated"`
96	SnapshotRlibs      []string `blueprint:"mutated"`
97	SnapshotDylibs     []string `blueprint:"mutated"`
98
99	// Make this module available when building for ramdisk.
100	// On device without a dedicated recovery partition, the module is only
101	// available after switching root into
102	// /first_stage_ramdisk. To expose the module before switching root, install
103	// the recovery variant instead.
104	Ramdisk_available *bool
105
106	// Make this module available when building for vendor ramdisk.
107	// On device without a dedicated recovery partition, the module is only
108	// available after switching root into
109	// /first_stage_ramdisk. To expose the module before switching root, install
110	// the recovery variant instead
111	Vendor_ramdisk_available *bool
112
113	// Normally Soong uses the directory structure to decide which modules
114	// should be included (framework) or excluded (non-framework) from the
115	// different snapshots (vendor, recovery, etc.), but this property
116	// allows a partner to exclude a module normally thought of as a
117	// framework module from the vendor snapshot.
118	Exclude_from_vendor_snapshot *bool
119
120	// Normally Soong uses the directory structure to decide which modules
121	// should be included (framework) or excluded (non-framework) from the
122	// different snapshots (vendor, recovery, etc.), but this property
123	// allows a partner to exclude a module normally thought of as a
124	// framework module from the recovery snapshot.
125	Exclude_from_recovery_snapshot *bool
126
127	// Make this module available when building for recovery
128	Recovery_available *bool
129
130	// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
131	Min_sdk_version *string
132
133	HideFromMake   bool `blueprint:"mutated"`
134	PreventInstall bool `blueprint:"mutated"`
135
136	Installable *bool
137}
138
139type Module struct {
140	fuzz.FuzzModule
141
142	VendorProperties cc.VendorProperties
143
144	Properties BaseProperties
145
146	hod        android.HostOrDeviceSupported
147	multilib   android.Multilib
148	testModule bool
149
150	makeLinkType string
151
152	afdo             *afdo
153	compiler         compiler
154	coverage         *coverage
155	clippy           *clippy
156	sanitize         *sanitize
157	cachedToolchain  config.Toolchain
158	sourceProvider   SourceProvider
159	subAndroidMkOnce map[SubAndroidMkProvider]bool
160
161	exportedLinkDirs []string
162
163	// Output file to be installed, may be stripped or unstripped.
164	outputFile android.OptionalPath
165
166	// Cross-reference input file
167	kytheFiles android.Paths
168
169	docTimestampFile android.OptionalPath
170
171	hideApexVariantFromMake bool
172
173	// For apex variants, this is set as apex.min_sdk_version
174	apexSdkVersion android.ApiLevel
175
176	transitiveAndroidMkSharedLibs *android.DepSet[string]
177}
178
179func (mod *Module) Header() bool {
180	//TODO: If Rust libraries provide header variants, this needs to be updated.
181	return false
182}
183
184func (mod *Module) SetPreventInstall() {
185	mod.Properties.PreventInstall = true
186}
187
188func (mod *Module) SetHideFromMake() {
189	mod.Properties.HideFromMake = true
190}
191
192func (mod *Module) HiddenFromMake() bool {
193	return mod.Properties.HideFromMake
194}
195
196func (mod *Module) SanitizePropDefined() bool {
197	// Because compiler is not set for some Rust modules where sanitize might be set, check that compiler is also not
198	// nil since we need compiler to actually sanitize.
199	return mod.sanitize != nil && mod.compiler != nil
200}
201
202func (mod *Module) IsPrebuilt() bool {
203	if _, ok := mod.compiler.(*prebuiltLibraryDecorator); ok {
204		return true
205	}
206	return false
207}
208
209func (mod *Module) OutputFiles(tag string) (android.Paths, error) {
210	switch tag {
211	case "":
212		if mod.sourceProvider != nil && (mod.compiler == nil || mod.compiler.Disabled()) {
213			return mod.sourceProvider.Srcs(), nil
214		} else {
215			if mod.OutputFile().Valid() {
216				return android.Paths{mod.OutputFile().Path()}, nil
217			}
218			return android.Paths{}, nil
219		}
220	case "unstripped":
221		if mod.compiler != nil {
222			return android.PathsIfNonNil(mod.compiler.unstrippedOutputFilePath()), nil
223		}
224		return nil, nil
225	default:
226		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
227	}
228}
229
230func (mod *Module) SelectedStl() string {
231	return ""
232}
233
234func (mod *Module) NonCcVariants() bool {
235	if mod.compiler != nil {
236		if library, ok := mod.compiler.(libraryInterface); ok {
237			return library.buildRlib() || library.buildDylib()
238		}
239	}
240	panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName()))
241}
242
243func (mod *Module) Static() bool {
244	if mod.compiler != nil {
245		if library, ok := mod.compiler.(libraryInterface); ok {
246			return library.static()
247		}
248	}
249	return false
250}
251
252func (mod *Module) Shared() bool {
253	if mod.compiler != nil {
254		if library, ok := mod.compiler.(libraryInterface); ok {
255			return library.shared()
256		}
257	}
258	return false
259}
260
261func (mod *Module) Dylib() bool {
262	if mod.compiler != nil {
263		if library, ok := mod.compiler.(libraryInterface); ok {
264			return library.dylib()
265		}
266	}
267	return false
268}
269
270func (mod *Module) Source() bool {
271	if mod.compiler != nil {
272		if library, ok := mod.compiler.(libraryInterface); ok && mod.sourceProvider != nil {
273			return library.source()
274		}
275	}
276	return false
277}
278
279func (mod *Module) RlibStd() bool {
280	if mod.compiler != nil {
281		if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() {
282			return library.rlibStd()
283		}
284	}
285	panic(fmt.Errorf("RlibStd() called on non-rlib module: %q", mod.BaseModuleName()))
286}
287
288func (mod *Module) Rlib() bool {
289	if mod.compiler != nil {
290		if library, ok := mod.compiler.(libraryInterface); ok {
291			return library.rlib()
292		}
293	}
294	return false
295}
296
297func (mod *Module) Binary() bool {
298	if binary, ok := mod.compiler.(binaryInterface); ok {
299		return binary.binary()
300	}
301	return false
302}
303
304func (mod *Module) StaticExecutable() bool {
305	if !mod.Binary() {
306		return false
307	}
308	return mod.StaticallyLinked()
309}
310
311func (mod *Module) Object() bool {
312	// Rust has no modules which produce only object files.
313	return false
314}
315
316func (mod *Module) Toc() android.OptionalPath {
317	if mod.compiler != nil {
318		if lib, ok := mod.compiler.(libraryInterface); ok {
319			return lib.toc()
320		}
321	}
322	panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName()))
323}
324
325func (mod *Module) UseSdk() bool {
326	return false
327}
328
329func (mod *Module) RelativeInstallPath() string {
330	if mod.compiler != nil {
331		return mod.compiler.relativeInstallPath()
332	}
333	return ""
334}
335
336func (mod *Module) UseVndk() bool {
337	return mod.Properties.VndkVersion != ""
338}
339
340func (mod *Module) Bootstrap() bool {
341	return Bool(mod.Properties.Bootstrap)
342}
343
344func (mod *Module) SubName() string {
345	return mod.Properties.SubName
346}
347
348func (mod *Module) IsVndkPrebuiltLibrary() bool {
349	// Rust modules do not provide VNDK prebuilts
350	return false
351}
352
353func (mod *Module) IsVendorPublicLibrary() bool {
354	return mod.VendorProperties.IsVendorPublicLibrary
355}
356
357func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool {
358	// Rust modules to not provide Sdk variants
359	return false
360}
361
362func (c *Module) IsVndkPrivate() bool {
363	return false
364}
365
366func (c *Module) IsLlndk() bool {
367	return false
368}
369
370func (mod *Module) KernelHeadersDecorator() bool {
371	return false
372}
373
374func (m *Module) NeedsLlndkVariants() bool {
375	return false
376}
377
378func (m *Module) NeedsVendorPublicLibraryVariants() bool {
379	return false
380}
381
382func (mod *Module) HasLlndkStubs() bool {
383	return false
384}
385
386func (mod *Module) StubsVersion() string {
387	panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", mod.BaseModuleName()))
388}
389
390func (mod *Module) SdkVersion() string {
391	return ""
392}
393
394func (mod *Module) AlwaysSdk() bool {
395	return false
396}
397
398func (mod *Module) IsSdkVariant() bool {
399	return false
400}
401
402func (mod *Module) SplitPerApiLevel() bool {
403	return false
404}
405
406func (mod *Module) XrefRustFiles() android.Paths {
407	return mod.kytheFiles
408}
409
410type Deps struct {
411	Dylibs          []string
412	Rlibs           []string
413	Rustlibs        []string
414	Stdlibs         []string
415	ProcMacros      []string
416	SharedLibs      []string
417	StaticLibs      []string
418	WholeStaticLibs []string
419	HeaderLibs      []string
420
421	// Used for data dependencies adjacent to tests
422	DataLibs []string
423	DataBins []string
424
425	CrtBegin, CrtEnd []string
426}
427
428type PathDeps struct {
429	DyLibs        RustLibraries
430	RLibs         RustLibraries
431	SharedLibs    android.Paths
432	SharedLibDeps android.Paths
433	StaticLibs    android.Paths
434	ProcMacros    RustLibraries
435	AfdoProfiles  android.Paths
436
437	// depFlags and depLinkFlags are rustc and linker (clang) flags.
438	depFlags     []string
439	depLinkFlags []string
440
441	// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker.
442	// Both of these are exported and propagate to dependencies.
443	linkDirs    []string
444	linkObjects []string
445
446	// exportedLinkDirs are exported linkDirs for direct rlib dependencies to
447	// cc_library_static dependants of rlibs.
448	// Track them separately from linkDirs so superfluous -L flags don't get emitted.
449	exportedLinkDirs []string
450
451	// Used by bindgen modules which call clang
452	depClangFlags         []string
453	depIncludePaths       android.Paths
454	depGeneratedHeaders   android.Paths
455	depSystemIncludePaths android.Paths
456
457	CrtBegin android.Paths
458	CrtEnd   android.Paths
459
460	// Paths to generated source files
461	SrcDeps          android.Paths
462	srcProviderFiles android.Paths
463
464	// Used by Generated Libraries
465	depExportedRlibs []cc.RustRlibDep
466}
467
468type RustLibraries []RustLibrary
469
470type RustLibrary struct {
471	Path      android.Path
472	CrateName string
473}
474
475type exportedFlagsProducer interface {
476	exportLinkDirs(...string)
477	exportLinkObjects(...string)
478}
479
480type xref interface {
481	XrefRustFiles() android.Paths
482}
483
484type flagExporter struct {
485	linkDirs    []string
486	linkObjects []string
487}
488
489func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
490	flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
491}
492
493func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
494	flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
495}
496
497func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
498	android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{
499		LinkDirs:    flagExporter.linkDirs,
500		LinkObjects: flagExporter.linkObjects,
501	})
502}
503
504var _ exportedFlagsProducer = (*flagExporter)(nil)
505
506func NewFlagExporter() *flagExporter {
507	return &flagExporter{}
508}
509
510type FlagExporterInfo struct {
511	Flags       []string
512	LinkDirs    []string // TODO: this should be android.Paths
513	LinkObjects []string // TODO: this should be android.Paths
514}
515
516var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]()
517
518func (mod *Module) isCoverageVariant() bool {
519	return mod.coverage.Properties.IsCoverageVariant
520}
521
522var _ cc.Coverage = (*Module)(nil)
523
524func (mod *Module) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
525	return mod.coverage != nil && mod.coverage.Properties.NeedCoverageVariant
526}
527
528func (mod *Module) VndkVersion() string {
529	return mod.Properties.VndkVersion
530}
531
532func (mod *Module) ExportedCrateLinkDirs() []string {
533	return mod.exportedLinkDirs
534}
535
536func (mod *Module) PreventInstall() bool {
537	return mod.Properties.PreventInstall
538}
539
540func (mod *Module) MarkAsCoverageVariant(coverage bool) {
541	mod.coverage.Properties.IsCoverageVariant = coverage
542}
543
544func (mod *Module) EnableCoverageIfNeeded() {
545	mod.coverage.Properties.CoverageEnabled = mod.coverage.Properties.NeedCoverageBuild
546}
547
548func defaultsFactory() android.Module {
549	return DefaultsFactory()
550}
551
552type Defaults struct {
553	android.ModuleBase
554	android.DefaultsModuleBase
555}
556
557func DefaultsFactory(props ...interface{}) android.Module {
558	module := &Defaults{}
559
560	module.AddProperties(props...)
561	module.AddProperties(
562		&BaseProperties{},
563		&cc.AfdoProperties{},
564		&cc.VendorProperties{},
565		&BenchmarkProperties{},
566		&BindgenProperties{},
567		&BaseCompilerProperties{},
568		&BinaryCompilerProperties{},
569		&LibraryCompilerProperties{},
570		&ProcMacroCompilerProperties{},
571		&PrebuiltProperties{},
572		&SourceProviderProperties{},
573		&TestProperties{},
574		&cc.CoverageProperties{},
575		&cc.RustBindgenClangProperties{},
576		&ClippyProperties{},
577		&SanitizeProperties{},
578		&fuzz.FuzzProperties{},
579	)
580
581	android.InitDefaultsModule(module)
582	return module
583}
584
585func (mod *Module) CrateName() string {
586	return mod.compiler.crateName()
587}
588
589func (mod *Module) CcLibrary() bool {
590	if mod.compiler != nil {
591		if _, ok := mod.compiler.(libraryInterface); ok {
592			return true
593		}
594	}
595	return false
596}
597
598func (mod *Module) CcLibraryInterface() bool {
599	if mod.compiler != nil {
600		// use build{Static,Shared}() instead of {static,shared}() here because this might be called before
601		// VariantIs{Static,Shared} is set.
602		if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic()) {
603			return true
604		}
605	}
606	return false
607}
608
609func (mod *Module) RustLibraryInterface() bool {
610	if mod.compiler != nil {
611		if _, ok := mod.compiler.(libraryInterface); ok {
612			return true
613		}
614	}
615	return false
616}
617
618func (mod *Module) IsFuzzModule() bool {
619	if _, ok := mod.compiler.(*fuzzDecorator); ok {
620		return true
621	}
622	return false
623}
624
625func (mod *Module) FuzzModuleStruct() fuzz.FuzzModule {
626	return mod.FuzzModule
627}
628
629func (mod *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
630	if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
631		return fuzzer.fuzzPackagedModule
632	}
633	panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", mod.BaseModuleName()))
634}
635
636func (mod *Module) FuzzSharedLibraries() android.RuleBuilderInstalls {
637	if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
638		return fuzzer.sharedLibraries
639	}
640	panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", mod.BaseModuleName()))
641}
642
643func (mod *Module) UnstrippedOutputFile() android.Path {
644	if mod.compiler != nil {
645		return mod.compiler.unstrippedOutputFilePath()
646	}
647	return nil
648}
649
650func (mod *Module) SetStatic() {
651	if mod.compiler != nil {
652		if library, ok := mod.compiler.(libraryInterface); ok {
653			library.setStatic()
654			return
655		}
656	}
657	panic(fmt.Errorf("SetStatic called on non-library module: %q", mod.BaseModuleName()))
658}
659
660func (mod *Module) SetShared() {
661	if mod.compiler != nil {
662		if library, ok := mod.compiler.(libraryInterface); ok {
663			library.setShared()
664			return
665		}
666	}
667	panic(fmt.Errorf("SetShared called on non-library module: %q", mod.BaseModuleName()))
668}
669
670func (mod *Module) BuildStaticVariant() bool {
671	if mod.compiler != nil {
672		if library, ok := mod.compiler.(libraryInterface); ok {
673			return library.buildStatic()
674		}
675	}
676	panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName()))
677}
678
679func (mod *Module) BuildSharedVariant() bool {
680	if mod.compiler != nil {
681		if library, ok := mod.compiler.(libraryInterface); ok {
682			return library.buildShared()
683		}
684	}
685	panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName()))
686}
687
688func (mod *Module) Module() android.Module {
689	return mod
690}
691
692func (mod *Module) OutputFile() android.OptionalPath {
693	return mod.outputFile
694}
695
696func (mod *Module) CoverageFiles() android.Paths {
697	if mod.compiler != nil {
698		return android.Paths{}
699	}
700	panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName()))
701}
702
703// Rust does not produce gcno files, and therefore does not produce a coverage archive.
704func (mod *Module) CoverageOutputFile() android.OptionalPath {
705	return android.OptionalPath{}
706}
707
708func (mod *Module) IsNdk(config android.Config) bool {
709	return false
710}
711
712func (mod *Module) IsStubs() bool {
713	return false
714}
715
716func (mod *Module) installable(apexInfo android.ApexInfo) bool {
717	if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) {
718		return false
719	}
720
721	// The apex variant is not installable because it is included in the APEX and won't appear
722	// in the system partition as a standalone file.
723	if !apexInfo.IsForPlatform() {
724		return false
725	}
726
727	return mod.OutputFile().Valid() && !mod.Properties.PreventInstall
728}
729
730func (ctx moduleContext) apexVariationName() string {
731	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
732	return apexInfo.ApexVariationName
733}
734
735var _ cc.LinkableInterface = (*Module)(nil)
736
737func (mod *Module) Init() android.Module {
738	mod.AddProperties(&mod.Properties)
739	mod.AddProperties(&mod.VendorProperties)
740
741	if mod.afdo != nil {
742		mod.AddProperties(mod.afdo.props()...)
743	}
744	if mod.compiler != nil {
745		mod.AddProperties(mod.compiler.compilerProps()...)
746	}
747	if mod.coverage != nil {
748		mod.AddProperties(mod.coverage.props()...)
749	}
750	if mod.clippy != nil {
751		mod.AddProperties(mod.clippy.props()...)
752	}
753	if mod.sourceProvider != nil {
754		mod.AddProperties(mod.sourceProvider.SourceProviderProps()...)
755	}
756	if mod.sanitize != nil {
757		mod.AddProperties(mod.sanitize.props()...)
758	}
759
760	android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
761	android.InitApexModule(mod)
762
763	android.InitDefaultableModule(mod)
764	return mod
765}
766
767func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
768	return &Module{
769		hod:      hod,
770		multilib: multilib,
771	}
772}
773func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
774	module := newBaseModule(hod, multilib)
775	module.afdo = &afdo{}
776	module.coverage = &coverage{}
777	module.clippy = &clippy{}
778	module.sanitize = &sanitize{}
779	return module
780}
781
782type ModuleContext interface {
783	android.ModuleContext
784	ModuleContextIntf
785}
786
787type BaseModuleContext interface {
788	android.BaseModuleContext
789	ModuleContextIntf
790}
791
792type DepsContext interface {
793	android.BottomUpMutatorContext
794	ModuleContextIntf
795}
796
797type ModuleContextIntf interface {
798	RustModule() *Module
799	toolchain() config.Toolchain
800}
801
802type depsContext struct {
803	android.BottomUpMutatorContext
804}
805
806type moduleContext struct {
807	android.ModuleContext
808}
809
810type baseModuleContext struct {
811	android.BaseModuleContext
812}
813
814func (ctx *moduleContext) RustModule() *Module {
815	return ctx.Module().(*Module)
816}
817
818func (ctx *moduleContext) toolchain() config.Toolchain {
819	return ctx.RustModule().toolchain(ctx)
820}
821
822func (ctx *depsContext) RustModule() *Module {
823	return ctx.Module().(*Module)
824}
825
826func (ctx *depsContext) toolchain() config.Toolchain {
827	return ctx.RustModule().toolchain(ctx)
828}
829
830func (ctx *baseModuleContext) RustModule() *Module {
831	return ctx.Module().(*Module)
832}
833
834func (ctx *baseModuleContext) toolchain() config.Toolchain {
835	return ctx.RustModule().toolchain(ctx)
836}
837
838func (mod *Module) nativeCoverage() bool {
839	// Bug: http://b/137883967 - native-bridge modules do not currently work with coverage
840	if mod.Target().NativeBridge == android.NativeBridgeEnabled {
841		return false
842	}
843	return mod.compiler != nil && mod.compiler.nativeCoverage()
844}
845
846func (mod *Module) EverInstallable() bool {
847	return mod.compiler != nil &&
848		// Check to see whether the module is actually ever installable.
849		mod.compiler.everInstallable()
850}
851
852func (mod *Module) Installable() *bool {
853	return mod.Properties.Installable
854}
855
856func (mod *Module) ProcMacro() bool {
857	if pm, ok := mod.compiler.(procMacroInterface); ok {
858		return pm.ProcMacro()
859	}
860	return false
861}
862
863func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
864	if mod.cachedToolchain == nil {
865		mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
866	}
867	return mod.cachedToolchain
868}
869
870func (mod *Module) ccToolchain(ctx android.BaseModuleContext) cc_config.Toolchain {
871	return cc_config.FindToolchain(ctx.Os(), ctx.Arch())
872}
873
874func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
875}
876
877func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
878	ctx := &moduleContext{
879		ModuleContext: actx,
880	}
881
882	apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
883	if !apexInfo.IsForPlatform() {
884		mod.hideApexVariantFromMake = true
885	}
886
887	toolchain := mod.toolchain(ctx)
888	mod.makeLinkType = cc.GetMakeLinkType(actx, mod)
889
890	mod.Properties.SubName = cc.GetSubnameProperty(actx, mod)
891
892	if !toolchain.Supported() {
893		// This toolchain's unsupported, there's nothing to do for this mod.
894		return
895	}
896
897	deps := mod.depsToPaths(ctx)
898	// Export linkDirs for CC rust generatedlibs
899	mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.exportedLinkDirs...)
900	mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.linkDirs...)
901
902	flags := Flags{
903		Toolchain: toolchain,
904	}
905
906	// Calculate rustc flags
907	if mod.afdo != nil {
908		flags, deps = mod.afdo.flags(actx, flags, deps)
909	}
910	if mod.compiler != nil {
911		flags = mod.compiler.compilerFlags(ctx, flags)
912		flags = mod.compiler.cfgFlags(ctx, flags)
913		flags = mod.compiler.featureFlags(ctx, flags)
914	}
915	if mod.coverage != nil {
916		flags, deps = mod.coverage.flags(ctx, flags, deps)
917	}
918	if mod.clippy != nil {
919		flags, deps = mod.clippy.flags(ctx, flags, deps)
920	}
921	if mod.sanitize != nil {
922		flags, deps = mod.sanitize.flags(ctx, flags, deps)
923	}
924
925	// SourceProvider needs to call GenerateSource() before compiler calls
926	// compile() so it can provide the source. A SourceProvider has
927	// multiple variants (e.g. source, rlib, dylib). Only the "source"
928	// variant is responsible for effectively generating the source. The
929	// remaining variants relies on the "source" variant output.
930	if mod.sourceProvider != nil {
931		if mod.compiler.(libraryInterface).source() {
932			mod.sourceProvider.GenerateSource(ctx, deps)
933			mod.sourceProvider.setSubName(ctx.ModuleSubDir())
934		} else {
935			sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag)
936			sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
937			mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
938		}
939		android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()})
940	}
941
942	if mod.compiler != nil && !mod.compiler.Disabled() {
943		mod.compiler.initialize(ctx)
944		buildOutput := mod.compiler.compile(ctx, flags, deps)
945		if ctx.Failed() {
946			return
947		}
948		mod.outputFile = android.OptionalPathForPath(buildOutput.outputFile)
949		if buildOutput.kytheFile != nil {
950			mod.kytheFiles = append(mod.kytheFiles, buildOutput.kytheFile)
951		}
952		bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), android.OptionalPathForPath(mod.compiler.unstrippedOutputFilePath()))
953
954		mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps)
955		if mod.docTimestampFile.Valid() {
956			ctx.CheckbuildFile(mod.docTimestampFile.Path())
957		}
958
959		apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
960		if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() {
961			// If the module has been specifically configure to not be installed then
962			// hide from make as otherwise it will break when running inside make as the
963			// output path to install will not be specified. Not all uninstallable
964			// modules can be hidden from make as some are needed for resolving make
965			// side dependencies. In particular, proc-macros need to be captured in the
966			// host snapshot.
967			mod.HideFromMake()
968		} else if !mod.installable(apexInfo) {
969			mod.SkipInstall()
970		}
971
972		// Still call install though, the installs will be stored as PackageSpecs to allow
973		// using the outputs in a genrule.
974		if mod.OutputFile().Valid() {
975			mod.compiler.install(ctx)
976			if ctx.Failed() {
977				return
978			}
979			// Export your own directory as a linkDir
980			mod.exportedLinkDirs = append(mod.exportedLinkDirs, linkPathFromFilePath(mod.OutputFile().Path()))
981
982		}
983
984		ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
985	}
986	if mod.testModule {
987		android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
988	}
989}
990
991func (mod *Module) deps(ctx DepsContext) Deps {
992	deps := Deps{}
993
994	if mod.compiler != nil {
995		deps = mod.compiler.compilerDeps(ctx, deps)
996	}
997	if mod.sourceProvider != nil {
998		deps = mod.sourceProvider.SourceProviderDeps(ctx, deps)
999	}
1000
1001	if mod.coverage != nil {
1002		deps = mod.coverage.deps(ctx, deps)
1003	}
1004
1005	if mod.sanitize != nil {
1006		deps = mod.sanitize.deps(ctx, deps)
1007	}
1008
1009	deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
1010	deps.Dylibs = android.LastUniqueStrings(deps.Dylibs)
1011	deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs)
1012	deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
1013	deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
1014	deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
1015	deps.Stdlibs = android.LastUniqueStrings(deps.Stdlibs)
1016	deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
1017	return deps
1018
1019}
1020
1021type dependencyTag struct {
1022	blueprint.BaseDependencyTag
1023	name      string
1024	library   bool
1025	procMacro bool
1026	dynamic   bool
1027}
1028
1029// InstallDepNeeded returns true for rlibs, dylibs, and proc macros so that they or their transitive
1030// dependencies (especially C/C++ shared libs) are installed as dependencies of a rust binary.
1031func (d dependencyTag) InstallDepNeeded() bool {
1032	return d.library || d.procMacro
1033}
1034
1035var _ android.InstallNeededDependencyTag = dependencyTag{}
1036
1037func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
1038	if d.library && d.dynamic {
1039		return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
1040	}
1041	return nil
1042}
1043
1044func (d dependencyTag) PropagateAconfigValidation() bool {
1045	return d == rlibDepTag || d == sourceDepTag
1046}
1047
1048var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
1049
1050var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}
1051
1052var (
1053	customBindgenDepTag = dependencyTag{name: "customBindgenTag"}
1054	rlibDepTag          = dependencyTag{name: "rlibTag", library: true}
1055	dylibDepTag         = dependencyTag{name: "dylib", library: true, dynamic: true}
1056	procMacroDepTag     = dependencyTag{name: "procMacro", procMacro: true}
1057	testPerSrcDepTag    = dependencyTag{name: "rust_unit_tests"}
1058	sourceDepTag        = dependencyTag{name: "source"}
1059	dataLibDepTag       = dependencyTag{name: "data lib"}
1060	dataBinDepTag       = dependencyTag{name: "data bin"}
1061)
1062
1063func IsDylibDepTag(depTag blueprint.DependencyTag) bool {
1064	tag, ok := depTag.(dependencyTag)
1065	return ok && tag == dylibDepTag
1066}
1067
1068func IsRlibDepTag(depTag blueprint.DependencyTag) bool {
1069	tag, ok := depTag.(dependencyTag)
1070	return ok && tag == rlibDepTag
1071}
1072
1073type autoDep struct {
1074	variation string
1075	depTag    dependencyTag
1076}
1077
1078var (
1079	rlibVariation  = "rlib"
1080	dylibVariation = "dylib"
1081	rlibAutoDep    = autoDep{variation: rlibVariation, depTag: rlibDepTag}
1082	dylibAutoDep   = autoDep{variation: dylibVariation, depTag: dylibDepTag}
1083)
1084
1085type autoDeppable interface {
1086	autoDep(ctx android.BottomUpMutatorContext) autoDep
1087}
1088
1089func (mod *Module) begin(ctx BaseModuleContext) {
1090	if mod.coverage != nil {
1091		mod.coverage.begin(ctx)
1092	}
1093	if mod.sanitize != nil {
1094		mod.sanitize.begin(ctx)
1095	}
1096}
1097
1098func (mod *Module) Prebuilt() *android.Prebuilt {
1099	if p, ok := mod.compiler.(rustPrebuilt); ok {
1100		return p.prebuilt()
1101	}
1102	return nil
1103}
1104
1105func (mod *Module) Symlinks() []string {
1106	// TODO update this to return the list of symlinks when Rust supports defining symlinks
1107	return nil
1108}
1109
1110func rustMakeLibName(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.LinkableInterface, depName string) string {
1111	if rustDep, ok := dep.(*Module); ok {
1112		// Use base module name for snapshots when exporting to Makefile.
1113		if snapshotPrebuilt, ok := rustDep.compiler.(cc.SnapshotInterface); ok {
1114			baseName := rustDep.BaseModuleName()
1115			return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix() + rustDep.AndroidMkSuffix()
1116		}
1117	}
1118	return cc.MakeLibName(ctx, c, dep, depName)
1119}
1120
1121func collectIncludedProtos(mod *Module, dep *Module) {
1122	if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok {
1123		if _, ok := dep.sourceProvider.(*protobufDecorator); ok {
1124			protoMod.additionalCrates = append(protoMod.additionalCrates, dep.CrateName())
1125		}
1126	}
1127}
1128
1129func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
1130	var depPaths PathDeps
1131
1132	directRlibDeps := []*Module{}
1133	directDylibDeps := []*Module{}
1134	directProcMacroDeps := []*Module{}
1135	directSharedLibDeps := []cc.SharedLibraryInfo{}
1136	directStaticLibDeps := [](cc.LinkableInterface){}
1137	directSrcProvidersDeps := []*Module{}
1138	directSrcDeps := [](android.SourceFileProducer){}
1139
1140	// For the dependency from platform to apex, use the latest stubs
1141	mod.apexSdkVersion = android.FutureApiLevel
1142	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
1143	if !apexInfo.IsForPlatform() {
1144		mod.apexSdkVersion = apexInfo.MinSdkVersion
1145	}
1146
1147	if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
1148		// In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000)
1149		// so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)).
1150		// (b/144430859)
1151		mod.apexSdkVersion = android.FutureApiLevel
1152	}
1153
1154	skipModuleList := map[string]bool{}
1155
1156	var apiImportInfo multitree.ApiImportInfo
1157	hasApiImportInfo := false
1158
1159	ctx.VisitDirectDeps(func(dep android.Module) {
1160		if dep.Name() == "api_imports" {
1161			apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider)
1162			hasApiImportInfo = true
1163		}
1164	})
1165
1166	if hasApiImportInfo {
1167		targetStubModuleList := map[string]string{}
1168		targetOrigModuleList := map[string]string{}
1169
1170		// Search for dependency which both original module and API imported library with APEX stub exists
1171		ctx.VisitDirectDeps(func(dep android.Module) {
1172			depName := ctx.OtherModuleName(dep)
1173			if apiLibrary, ok := apiImportInfo.ApexSharedLibs[depName]; ok {
1174				targetStubModuleList[apiLibrary] = depName
1175			}
1176		})
1177		ctx.VisitDirectDeps(func(dep android.Module) {
1178			depName := ctx.OtherModuleName(dep)
1179			if origLibrary, ok := targetStubModuleList[depName]; ok {
1180				targetOrigModuleList[origLibrary] = depName
1181			}
1182		})
1183
1184		// Decide which library should be used between original and API imported library
1185		ctx.VisitDirectDeps(func(dep android.Module) {
1186			depName := ctx.OtherModuleName(dep)
1187			if apiLibrary, ok := targetOrigModuleList[depName]; ok {
1188				if cc.ShouldUseStubForApex(ctx, dep) {
1189					skipModuleList[depName] = true
1190				} else {
1191					skipModuleList[apiLibrary] = true
1192				}
1193			}
1194		})
1195	}
1196
1197	var transitiveAndroidMkSharedLibs []*android.DepSet[string]
1198	var directAndroidMkSharedLibs []string
1199
1200	ctx.VisitDirectDeps(func(dep android.Module) {
1201		depName := ctx.OtherModuleName(dep)
1202		depTag := ctx.OtherModuleDependencyTag(dep)
1203
1204		if _, exists := skipModuleList[depName]; exists {
1205			return
1206		}
1207
1208		if depTag == android.DarwinUniversalVariantTag {
1209			return
1210		}
1211
1212		if rustDep, ok := dep.(*Module); ok && !rustDep.Static() && !rustDep.Shared() {
1213			//Handle Rust Modules
1214			makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
1215
1216			switch depTag {
1217			case dylibDepTag:
1218				dylib, ok := rustDep.compiler.(libraryInterface)
1219				if !ok || !dylib.dylib() {
1220					ctx.ModuleErrorf("mod %q not an dylib library", depName)
1221					return
1222				}
1223				directDylibDeps = append(directDylibDeps, rustDep)
1224				mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName)
1225				mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName))
1226
1227			case rlibDepTag:
1228
1229				rlib, ok := rustDep.compiler.(libraryInterface)
1230				if !ok || !rlib.rlib() {
1231					ctx.ModuleErrorf("mod %q not an rlib library", makeLibName)
1232					return
1233				}
1234				directRlibDeps = append(directRlibDeps, rustDep)
1235				mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName)
1236				mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName))
1237
1238				// rust_ffi rlibs may export include dirs, so collect those here.
1239				exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
1240				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
1241				depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
1242
1243			case procMacroDepTag:
1244				directProcMacroDeps = append(directProcMacroDeps, rustDep)
1245				mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
1246				// proc_macro link dirs need to be exported, so collect those here.
1247				depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
1248
1249			case sourceDepTag:
1250				if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
1251					collectIncludedProtos(mod, rustDep)
1252				}
1253			}
1254
1255			transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs)
1256
1257			if android.IsSourceDepTagWithOutputTag(depTag, "") {
1258				// Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct
1259				// OS/Arch variant is used.
1260				var helper string
1261				if ctx.Host() {
1262					helper = "missing 'host_supported'?"
1263				} else {
1264					helper = "device module defined?"
1265				}
1266
1267				if dep.Target().Os != ctx.Os() {
1268					ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper)
1269					return
1270				} else if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
1271					ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper)
1272					return
1273				}
1274				directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep)
1275			}
1276
1277			exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
1278			//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
1279			if depTag != procMacroDepTag {
1280				depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
1281				depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
1282				depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
1283			}
1284
1285			if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
1286				linkFile := rustDep.UnstrippedOutputFile()
1287				linkDir := linkPathFromFilePath(linkFile)
1288				if lib, ok := mod.compiler.(exportedFlagsProducer); ok {
1289					lib.exportLinkDirs(linkDir)
1290				}
1291			}
1292
1293			if depTag == sourceDepTag {
1294				if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() {
1295					if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok {
1296						exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
1297						depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
1298					}
1299				}
1300			}
1301		} else if ccDep, ok := dep.(cc.LinkableInterface); ok {
1302			//Handle C dependencies
1303			makeLibName := cc.MakeLibName(ctx, mod, ccDep, depName)
1304			if _, ok := ccDep.(*Module); !ok {
1305				if ccDep.Module().Target().Os != ctx.Os() {
1306					ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
1307					return
1308				}
1309				if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType {
1310					ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
1311					return
1312				}
1313			}
1314			linkObject := ccDep.OutputFile()
1315			if !linkObject.Valid() {
1316				if !ctx.Config().AllowMissingDependencies() {
1317					ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
1318				} else {
1319					ctx.AddMissingDependencies([]string{depName})
1320				}
1321				return
1322			}
1323
1324			linkPath := linkPathFromFilePath(linkObject.Path())
1325
1326			exportDep := false
1327			switch {
1328			case cc.IsStaticDepTag(depTag):
1329				if cc.IsWholeStaticLib(depTag) {
1330					// rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail
1331					// if the library is not prefixed by "lib".
1332					if mod.Binary() {
1333						// Binaries may sometimes need to link whole static libraries that don't start with 'lib'.
1334						// Since binaries don't need to 'rebundle' these like libraries and only use these for the
1335						// final linkage, pass the args directly to the linker to handle these cases.
1336						depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", linkObject.Path().String(), "-Wl,--no-whole-archive"}...)
1337					} else if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
1338						depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
1339					} else {
1340						ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName())
1341					}
1342				}
1343
1344				// Add this to linkObjects to pass the library directly to the linker as well. This propagates
1345				// to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
1346				depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
1347				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
1348
1349				exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
1350				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
1351				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
1352				depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
1353				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
1354				directStaticLibDeps = append(directStaticLibDeps, ccDep)
1355
1356				// Record baseLibName for snapshots.
1357				mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName))
1358
1359				mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, makeLibName)
1360			case cc.IsSharedDepTag(depTag):
1361				// For the shared lib dependencies, we may link to the stub variant
1362				// of the dependency depending on the context (e.g. if this
1363				// dependency crosses the APEX boundaries).
1364				sharedLibraryInfo, exportedInfo := cc.ChooseStubOrImpl(ctx, dep)
1365
1366				// Re-get linkObject as ChooseStubOrImpl actually tells us which
1367				// object (either from stub or non-stub) to use.
1368				linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
1369				if !linkObject.Valid() {
1370					if !ctx.Config().AllowMissingDependencies() {
1371						ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
1372					} else {
1373						ctx.AddMissingDependencies([]string{depName})
1374					}
1375					return
1376				}
1377				linkPath = linkPathFromFilePath(linkObject.Path())
1378
1379				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
1380				depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
1381				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
1382				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
1383				depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
1384				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
1385				directSharedLibDeps = append(directSharedLibDeps, sharedLibraryInfo)
1386
1387				// Record baseLibName for snapshots.
1388				mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName))
1389
1390				directAndroidMkSharedLibs = append(directAndroidMkSharedLibs, makeLibName)
1391				exportDep = true
1392			case cc.IsHeaderDepTag(depTag):
1393				exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
1394				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
1395				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
1396				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
1397				mod.Properties.AndroidMkHeaderLibs = append(mod.Properties.AndroidMkHeaderLibs, makeLibName)
1398			case depTag == cc.CrtBeginDepTag:
1399				depPaths.CrtBegin = append(depPaths.CrtBegin, linkObject.Path())
1400			case depTag == cc.CrtEndDepTag:
1401				depPaths.CrtEnd = append(depPaths.CrtEnd, linkObject.Path())
1402			}
1403
1404			// Make sure these dependencies are propagated
1405			if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
1406				lib.exportLinkDirs(linkPath)
1407				lib.exportLinkObjects(linkObject.String())
1408			}
1409		} else {
1410			switch {
1411			case depTag == cc.CrtBeginDepTag:
1412				depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, ""))
1413			case depTag == cc.CrtEndDepTag:
1414				depPaths.CrtEnd = append(depPaths.CrtEnd, android.OutputFileForModule(ctx, dep, ""))
1415			}
1416		}
1417
1418		if srcDep, ok := dep.(android.SourceFileProducer); ok {
1419			if android.IsSourceDepTagWithOutputTag(depTag, "") {
1420				// These are usually genrules which don't have per-target variants.
1421				directSrcDeps = append(directSrcDeps, srcDep)
1422			}
1423		}
1424	})
1425
1426	mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs)
1427
1428	var rlibDepFiles RustLibraries
1429	aliases := mod.compiler.Aliases()
1430	for _, dep := range directRlibDeps {
1431		crateName := dep.CrateName()
1432		if alias, aliased := aliases[crateName]; aliased {
1433			crateName = alias
1434		}
1435		rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
1436	}
1437	var dylibDepFiles RustLibraries
1438	for _, dep := range directDylibDeps {
1439		crateName := dep.CrateName()
1440		if alias, aliased := aliases[crateName]; aliased {
1441			crateName = alias
1442		}
1443		dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
1444	}
1445	var procMacroDepFiles RustLibraries
1446	for _, dep := range directProcMacroDeps {
1447		crateName := dep.CrateName()
1448		if alias, aliased := aliases[crateName]; aliased {
1449			crateName = alias
1450		}
1451		procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
1452	}
1453
1454	var staticLibDepFiles android.Paths
1455	for _, dep := range directStaticLibDeps {
1456		staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path())
1457	}
1458
1459	var sharedLibFiles android.Paths
1460	var sharedLibDepFiles android.Paths
1461	for _, dep := range directSharedLibDeps {
1462		sharedLibFiles = append(sharedLibFiles, dep.SharedLibrary)
1463		if dep.TableOfContents.Valid() {
1464			sharedLibDepFiles = append(sharedLibDepFiles, dep.TableOfContents.Path())
1465		} else {
1466			sharedLibDepFiles = append(sharedLibDepFiles, dep.SharedLibrary)
1467		}
1468	}
1469
1470	var srcProviderDepFiles android.Paths
1471	for _, dep := range directSrcProvidersDeps {
1472		srcs, _ := dep.OutputFiles("")
1473		srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
1474	}
1475	for _, dep := range directSrcDeps {
1476		srcs := dep.Srcs()
1477		srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
1478	}
1479
1480	depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
1481	depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
1482	depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibFiles...)
1483	depPaths.SharedLibDeps = append(depPaths.SharedLibDeps, sharedLibDepFiles...)
1484	depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
1485	depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
1486	depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...)
1487
1488	// Dedup exported flags from dependencies
1489	depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
1490	depPaths.linkObjects = android.FirstUniqueStrings(depPaths.linkObjects)
1491	depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
1492	depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags)
1493	depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
1494	depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
1495
1496	return depPaths
1497}
1498
1499func (mod *Module) InstallInData() bool {
1500	if mod.compiler == nil {
1501		return false
1502	}
1503	return mod.compiler.inData()
1504}
1505
1506func (mod *Module) InstallInRamdisk() bool {
1507	return mod.InRamdisk()
1508}
1509
1510func (mod *Module) InstallInVendorRamdisk() bool {
1511	return mod.InVendorRamdisk()
1512}
1513
1514func (mod *Module) InstallInRecovery() bool {
1515	return mod.InRecovery()
1516}
1517
1518func linkPathFromFilePath(filepath android.Path) string {
1519	return strings.Split(filepath.String(), filepath.Base())[0]
1520}
1521
1522// usePublicApi returns true if the rust variant should link against NDK (publicapi)
1523func (r *Module) usePublicApi() bool {
1524	return r.Device() && r.UseSdk()
1525}
1526
1527// useVendorApi returns true if the rust variant should link against LLNDK (vendorapi)
1528func (r *Module) useVendorApi() bool {
1529	return r.Device() && (r.InVendor() || r.InProduct())
1530}
1531
1532func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
1533	ctx := &depsContext{
1534		BottomUpMutatorContext: actx,
1535	}
1536
1537	deps := mod.deps(ctx)
1538	var commonDepVariations []blueprint.Variation
1539
1540	apiImportInfo := cc.GetApiImports(mod, actx)
1541	if mod.usePublicApi() || mod.useVendorApi() {
1542		for idx, lib := range deps.SharedLibs {
1543			deps.SharedLibs[idx] = cc.GetReplaceModuleName(lib, apiImportInfo.SharedLibs)
1544		}
1545	}
1546
1547	if ctx.Os() == android.Android {
1548		deps.SharedLibs, _ = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs)
1549	}
1550
1551	stdLinkage := "dylib-std"
1552	if mod.compiler.stdLinkage(ctx) == RlibLinkage {
1553		stdLinkage = "rlib-std"
1554	}
1555
1556	rlibDepVariations := commonDepVariations
1557	rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
1558
1559	if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() {
1560		rlibDepVariations = append(rlibDepVariations,
1561			blueprint.Variation{Mutator: "rust_stdlinkage", Variation: stdLinkage})
1562	}
1563
1564	// rlibs
1565	rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: rlibVariation})
1566	for _, lib := range deps.Rlibs {
1567		depTag := rlibDepTag
1568		actx.AddVariationDependencies(rlibDepVariations, depTag, lib)
1569	}
1570
1571	// dylibs
1572	dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation})
1573	dylibDepVariations = append(dylibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
1574
1575	for _, lib := range deps.Dylibs {
1576		actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib)
1577	}
1578
1579	// rustlibs
1580	if deps.Rustlibs != nil {
1581		if !mod.compiler.Disabled() {
1582			for _, lib := range deps.Rustlibs {
1583				autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
1584				if autoDep.depTag == rlibDepTag {
1585					// Handle the rlib deptag case
1586					actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib)
1587
1588				} else {
1589					// autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however.
1590					// Check for the existence of the dylib deptag variant. Select it if available,
1591					// otherwise select the rlib variant.
1592					autoDepVariations := append(commonDepVariations,
1593						blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
1594					autoDepVariations = append(autoDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
1595					if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) {
1596						actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
1597
1598					} else {
1599						// If there's no dylib dependency available, try to add the rlib dependency instead.
1600						actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib)
1601
1602					}
1603				}
1604			}
1605		} else if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
1606			for _, lib := range deps.Rustlibs {
1607				srcProviderVariations := append(commonDepVariations,
1608					blueprint.Variation{Mutator: "rust_libraries", Variation: "source"})
1609				srcProviderVariations = append(srcProviderVariations, blueprint.Variation{Mutator: "link", Variation: ""})
1610
1611				// Only add rustlib dependencies if they're source providers themselves.
1612				// This is used to track which crate names need to be added to the source generated
1613				// in the rust_protobuf mod.rs.
1614				if actx.OtherModuleDependencyVariantExists(srcProviderVariations, lib) {
1615					actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib)
1616				}
1617			}
1618		}
1619	}
1620
1621	// stdlibs
1622	if deps.Stdlibs != nil {
1623		if mod.compiler.stdLinkage(ctx) == RlibLinkage {
1624			for _, lib := range deps.Stdlibs {
1625				actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}...),
1626					rlibDepTag, lib)
1627			}
1628		} else {
1629			for _, lib := range deps.Stdlibs {
1630				actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib)
1631
1632			}
1633		}
1634	}
1635
1636	for _, lib := range deps.SharedLibs {
1637		depTag := cc.SharedDepTag()
1638		name, version := cc.StubsLibNameAndVersion(lib)
1639
1640		variations := []blueprint.Variation{
1641			{Mutator: "link", Variation: "shared"},
1642		}
1643		// For core variant, add a dep on the implementation (if it exists) and its .apiimport (if it exists)
1644		// GenerateAndroidBuildActions will pick the correct impl/stub based on the api_domain boundary
1645		if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
1646			cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
1647		}
1648
1649		if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok {
1650			cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, apiLibraryName, version, false)
1651		}
1652	}
1653
1654	for _, lib := range deps.WholeStaticLibs {
1655		depTag := cc.StaticDepTag(true)
1656
1657		actx.AddVariationDependencies([]blueprint.Variation{
1658			{Mutator: "link", Variation: "static"},
1659		}, depTag, lib)
1660	}
1661
1662	for _, lib := range deps.StaticLibs {
1663		depTag := cc.StaticDepTag(false)
1664
1665		actx.AddVariationDependencies([]blueprint.Variation{
1666			{Mutator: "link", Variation: "static"},
1667		}, depTag, lib)
1668	}
1669
1670	actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)
1671
1672	crtVariations := cc.GetCrtVariations(ctx, mod)
1673	for _, crt := range deps.CrtBegin {
1674		actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, crt)
1675	}
1676	for _, crt := range deps.CrtEnd {
1677		actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, crt)
1678	}
1679
1680	if mod.sourceProvider != nil {
1681		if bindgen, ok := mod.sourceProvider.(*bindgenDecorator); ok &&
1682			bindgen.Properties.Custom_bindgen != "" {
1683			actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), customBindgenDepTag,
1684				bindgen.Properties.Custom_bindgen)
1685		}
1686	}
1687
1688	actx.AddVariationDependencies([]blueprint.Variation{
1689		{Mutator: "link", Variation: "shared"},
1690	}, dataLibDepTag, deps.DataLibs...)
1691
1692	actx.AddVariationDependencies(nil, dataBinDepTag, deps.DataBins...)
1693
1694	// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
1695	actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
1696
1697	mod.afdo.addDep(ctx, actx)
1698}
1699
1700func BeginMutator(ctx android.BottomUpMutatorContext) {
1701	if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) {
1702		mod.beginMutator(ctx)
1703	}
1704}
1705
1706func (mod *Module) beginMutator(actx android.BottomUpMutatorContext) {
1707	ctx := &baseModuleContext{
1708		BaseModuleContext: actx,
1709	}
1710
1711	mod.begin(ctx)
1712}
1713
1714func (mod *Module) Name() string {
1715	name := mod.ModuleBase.Name()
1716	if p, ok := mod.compiler.(interface {
1717		Name(string) string
1718	}); ok {
1719		name = p.Name(name)
1720	}
1721	return name
1722}
1723
1724func (mod *Module) disableClippy() {
1725	if mod.clippy != nil {
1726		mod.clippy.Properties.Clippy_lints = proptools.StringPtr("none")
1727	}
1728}
1729
1730var _ android.HostToolProvider = (*Module)(nil)
1731
1732func (mod *Module) HostToolPath() android.OptionalPath {
1733	if !mod.Host() {
1734		return android.OptionalPath{}
1735	}
1736	if binary, ok := mod.compiler.(*binaryDecorator); ok {
1737		return android.OptionalPathForPath(binary.baseCompiler.path)
1738	} else if pm, ok := mod.compiler.(*procMacroDecorator); ok {
1739		// Even though proc-macros aren't strictly "tools", since they target the compiler
1740		// and act as compiler plugins, we treat them similarly.
1741		return android.OptionalPathForPath(pm.baseCompiler.path)
1742	}
1743	return android.OptionalPath{}
1744}
1745
1746var _ android.ApexModule = (*Module)(nil)
1747
1748func (mod *Module) MinSdkVersion() string {
1749	return String(mod.Properties.Min_sdk_version)
1750}
1751
1752// Implements android.ApexModule
1753func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
1754	minSdkVersion := mod.MinSdkVersion()
1755	if minSdkVersion == "apex_inherit" {
1756		return nil
1757	}
1758	if minSdkVersion == "" {
1759		return fmt.Errorf("min_sdk_version is not specificed")
1760	}
1761
1762	// Not using nativeApiLevelFromUser because the context here is not
1763	// necessarily a native context.
1764	ver, err := android.ApiLevelFromUser(ctx, minSdkVersion)
1765	if err != nil {
1766		return err
1767	}
1768
1769	if ver.GreaterThan(sdkVersion) {
1770		return fmt.Errorf("newer SDK(%v)", ver)
1771	}
1772	return nil
1773}
1774
1775// Implements android.ApexModule
1776func (mod *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
1777	depTag := ctx.OtherModuleDependencyTag(dep)
1778
1779	if ccm, ok := dep.(*cc.Module); ok {
1780		if ccm.HasStubsVariants() {
1781			if cc.IsSharedDepTag(depTag) {
1782				// dynamic dep to a stubs lib crosses APEX boundary
1783				return false
1784			}
1785			if cc.IsRuntimeDepTag(depTag) {
1786				// runtime dep to a stubs lib also crosses APEX boundary
1787				return false
1788			}
1789
1790			if cc.IsHeaderDepTag(depTag) {
1791				return false
1792			}
1793		}
1794		if mod.Static() && cc.IsSharedDepTag(depTag) {
1795			// shared_lib dependency from a static lib is considered as crossing
1796			// the APEX boundary because the dependency doesn't actually is
1797			// linked; the dependency is used only during the compilation phase.
1798			return false
1799		}
1800	}
1801
1802	if depTag == procMacroDepTag || depTag == customBindgenDepTag {
1803		return false
1804	}
1805
1806	return true
1807}
1808
1809// Overrides ApexModule.IsInstallabeToApex()
1810func (mod *Module) IsInstallableToApex() bool {
1811	if mod.compiler != nil {
1812		if lib, ok := mod.compiler.(libraryInterface); ok && (lib.shared() || lib.dylib()) {
1813			return true
1814		}
1815		if _, ok := mod.compiler.(*binaryDecorator); ok {
1816			return true
1817		}
1818	}
1819	return false
1820}
1821
1822// If a library file has a "lib" prefix, extract the library name without the prefix.
1823func libNameFromFilePath(filepath android.Path) (string, bool) {
1824	libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
1825	if strings.HasPrefix(libName, "lib") {
1826		libName = libName[3:]
1827		return libName, true
1828	}
1829	return "", false
1830}
1831
1832func kytheExtractRustFactory() android.Singleton {
1833	return &kytheExtractRustSingleton{}
1834}
1835
1836type kytheExtractRustSingleton struct {
1837}
1838
1839func (k kytheExtractRustSingleton) GenerateBuildActions(ctx android.SingletonContext) {
1840	var xrefTargets android.Paths
1841	ctx.VisitAllModules(func(module android.Module) {
1842		if rustModule, ok := module.(xref); ok {
1843			xrefTargets = append(xrefTargets, rustModule.XrefRustFiles()...)
1844		}
1845	})
1846	if len(xrefTargets) > 0 {
1847		ctx.Phony("xref_rust", xrefTargets...)
1848	}
1849}
1850
1851func (c *Module) Partition() string {
1852	return ""
1853}
1854
1855var Bool = proptools.Bool
1856var BoolDefault = proptools.BoolDefault
1857var String = proptools.String
1858var StringPtr = proptools.StringPtr
1859
1860var _ android.OutputFileProducer = (*Module)(nil)
1861