• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"regexp"
20	"strings"
21
22	"android/soong/android"
23	"android/soong/cc"
24	"android/soong/snapshot"
25)
26
27var (
28	DylibStdlibSuffix = ".dylib-std"
29	RlibStdlibSuffix  = ".rlib-std"
30)
31
32func init() {
33	android.RegisterModuleType("rust_library", RustLibraryFactory)
34	android.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory)
35	android.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory)
36	android.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
37	android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
38	android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
39	android.RegisterModuleType("rust_ffi", RustFFIFactory)
40	android.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
41	android.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)
42	android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
43	android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
44	android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
45}
46
47type VariantLibraryProperties struct {
48	Enabled *bool    `android:"arch_variant"`
49	Srcs    []string `android:"path,arch_variant"`
50}
51
52type LibraryCompilerProperties struct {
53	Rlib   VariantLibraryProperties `android:"arch_variant"`
54	Dylib  VariantLibraryProperties `android:"arch_variant"`
55	Shared VariantLibraryProperties `android:"arch_variant"`
56	Static VariantLibraryProperties `android:"arch_variant"`
57
58	// path to include directories to pass to cc_* modules, only relevant for static/shared variants.
59	Include_dirs []string `android:"path,arch_variant"`
60
61	// Whether this library is part of the Rust toolchain sysroot.
62	Sysroot *bool
63}
64
65type LibraryMutatedProperties struct {
66	// Build a dylib variant
67	BuildDylib bool `blueprint:"mutated"`
68	// Build an rlib variant
69	BuildRlib bool `blueprint:"mutated"`
70	// Build a shared library variant
71	BuildShared bool `blueprint:"mutated"`
72	// Build a static library variant
73	BuildStatic bool `blueprint:"mutated"`
74
75	// This variant is a dylib
76	VariantIsDylib bool `blueprint:"mutated"`
77	// This variant is an rlib
78	VariantIsRlib bool `blueprint:"mutated"`
79	// This variant is a shared library
80	VariantIsShared bool `blueprint:"mutated"`
81	// This variant is a static library
82	VariantIsStatic bool `blueprint:"mutated"`
83	// This variant is a source provider
84	VariantIsSource bool `blueprint:"mutated"`
85
86	// This variant is disabled and should not be compiled
87	// (used for SourceProvider variants that produce only source)
88	VariantIsDisabled bool `blueprint:"mutated"`
89
90	// Whether this library variant should be link libstd via rlibs
91	VariantIsStaticStd bool `blueprint:"mutated"`
92}
93
94type libraryDecorator struct {
95	*baseCompiler
96	*flagExporter
97	stripper Stripper
98
99	Properties        LibraryCompilerProperties
100	MutatedProperties LibraryMutatedProperties
101	includeDirs       android.Paths
102	sourceProvider    SourceProvider
103
104	collectedSnapshotHeaders android.Paths
105
106	// table-of-contents file for cdylib crates to optimize out relinking when possible
107	tocFile android.OptionalPath
108}
109
110type libraryInterface interface {
111	rlib() bool
112	dylib() bool
113	static() bool
114	shared() bool
115	sysroot() bool
116	source() bool
117
118	// Returns true if the build options for the module have selected a particular build type
119	buildRlib() bool
120	buildDylib() bool
121	buildShared() bool
122	buildStatic() bool
123
124	// Sets a particular variant type
125	setRlib()
126	setDylib()
127	setShared()
128	setStatic()
129	setSource()
130
131	// libstd linkage functions
132	rlibStd() bool
133	setRlibStd()
134	setDylibStd()
135
136	// Build a specific library variant
137	BuildOnlyFFI()
138	BuildOnlyRust()
139	BuildOnlyRlib()
140	BuildOnlyDylib()
141	BuildOnlyStatic()
142	BuildOnlyShared()
143
144	toc() android.OptionalPath
145}
146
147func (library *libraryDecorator) nativeCoverage() bool {
148	return true
149}
150
151func (library *libraryDecorator) toc() android.OptionalPath {
152	return library.tocFile
153}
154
155func (library *libraryDecorator) rlib() bool {
156	return library.MutatedProperties.VariantIsRlib
157}
158
159func (library *libraryDecorator) sysroot() bool {
160	return Bool(library.Properties.Sysroot)
161}
162
163func (library *libraryDecorator) dylib() bool {
164	return library.MutatedProperties.VariantIsDylib
165}
166
167func (library *libraryDecorator) shared() bool {
168	return library.MutatedProperties.VariantIsShared
169}
170
171func (library *libraryDecorator) static() bool {
172	return library.MutatedProperties.VariantIsStatic
173}
174
175func (library *libraryDecorator) source() bool {
176	return library.MutatedProperties.VariantIsSource
177}
178
179func (library *libraryDecorator) buildRlib() bool {
180	return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true)
181}
182
183func (library *libraryDecorator) buildDylib() bool {
184	return library.MutatedProperties.BuildDylib && BoolDefault(library.Properties.Dylib.Enabled, true)
185}
186
187func (library *libraryDecorator) buildShared() bool {
188	return library.MutatedProperties.BuildShared && BoolDefault(library.Properties.Shared.Enabled, true)
189}
190
191func (library *libraryDecorator) buildStatic() bool {
192	return library.MutatedProperties.BuildStatic && BoolDefault(library.Properties.Static.Enabled, true)
193}
194
195func (library *libraryDecorator) setRlib() {
196	library.MutatedProperties.VariantIsRlib = true
197	library.MutatedProperties.VariantIsDylib = false
198	library.MutatedProperties.VariantIsStatic = false
199	library.MutatedProperties.VariantIsShared = false
200}
201
202func (library *libraryDecorator) setDylib() {
203	library.MutatedProperties.VariantIsRlib = false
204	library.MutatedProperties.VariantIsDylib = true
205	library.MutatedProperties.VariantIsStatic = false
206	library.MutatedProperties.VariantIsShared = false
207}
208
209func (library *libraryDecorator) rlibStd() bool {
210	return library.MutatedProperties.VariantIsStaticStd
211}
212
213func (library *libraryDecorator) setRlibStd() {
214	library.MutatedProperties.VariantIsStaticStd = true
215}
216
217func (library *libraryDecorator) setDylibStd() {
218	library.MutatedProperties.VariantIsStaticStd = false
219}
220
221func (library *libraryDecorator) setShared() {
222	library.MutatedProperties.VariantIsStatic = false
223	library.MutatedProperties.VariantIsShared = true
224	library.MutatedProperties.VariantIsRlib = false
225	library.MutatedProperties.VariantIsDylib = false
226}
227
228func (library *libraryDecorator) setStatic() {
229	library.MutatedProperties.VariantIsStatic = true
230	library.MutatedProperties.VariantIsShared = false
231	library.MutatedProperties.VariantIsRlib = false
232	library.MutatedProperties.VariantIsDylib = false
233}
234
235func (library *libraryDecorator) setSource() {
236	library.MutatedProperties.VariantIsSource = true
237}
238
239func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
240	if ctx.Module().(*Module).InVendor() {
241		// Vendor modules should statically link libstd.
242		return rlibAutoDep
243	} else if library.preferRlib() {
244		return rlibAutoDep
245	} else if library.rlib() || library.static() {
246		return rlibAutoDep
247	} else if library.dylib() || library.shared() {
248		return dylibAutoDep
249	} else if ctx.BazelConversionMode() {
250		// In Bazel conversion mode, we are currently ignoring the deptag, so we just need to supply a
251		// compatible tag in order to add the dependency.
252		return rlibAutoDep
253	} else {
254		panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName()))
255	}
256}
257
258func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
259	if ctx.RustModule().InVendor() {
260		// Vendor modules should statically link libstd.
261		return RlibLinkage
262	} else if library.static() || library.MutatedProperties.VariantIsStaticStd {
263		return RlibLinkage
264	} else if library.baseCompiler.preferRlib() {
265		return RlibLinkage
266	}
267	return DefaultLinkage
268}
269
270var _ compiler = (*libraryDecorator)(nil)
271var _ libraryInterface = (*libraryDecorator)(nil)
272var _ exportedFlagsProducer = (*libraryDecorator)(nil)
273
274// rust_library produces all rust variants.
275func RustLibraryFactory() android.Module {
276	module, library := NewRustLibrary(android.HostAndDeviceSupported)
277	library.BuildOnlyRust()
278	return module.Init()
279}
280
281// rust_ffi produces all ffi variants.
282func RustFFIFactory() android.Module {
283	module, library := NewRustLibrary(android.HostAndDeviceSupported)
284	library.BuildOnlyFFI()
285	return module.Init()
286}
287
288// rust_library_dylib produces a dylib.
289func RustLibraryDylibFactory() android.Module {
290	module, library := NewRustLibrary(android.HostAndDeviceSupported)
291	library.BuildOnlyDylib()
292	return module.Init()
293}
294
295// rust_library_rlib produces an rlib.
296func RustLibraryRlibFactory() android.Module {
297	module, library := NewRustLibrary(android.HostAndDeviceSupported)
298	library.BuildOnlyRlib()
299	return module.Init()
300}
301
302// rust_ffi_shared produces a shared library.
303func RustFFISharedFactory() android.Module {
304	module, library := NewRustLibrary(android.HostAndDeviceSupported)
305	library.BuildOnlyShared()
306	return module.Init()
307}
308
309// rust_ffi_static produces a static library.
310func RustFFIStaticFactory() android.Module {
311	module, library := NewRustLibrary(android.HostAndDeviceSupported)
312	library.BuildOnlyStatic()
313	return module.Init()
314}
315
316// rust_library_host produces all rust variants.
317func RustLibraryHostFactory() android.Module {
318	module, library := NewRustLibrary(android.HostSupported)
319	library.BuildOnlyRust()
320	return module.Init()
321}
322
323// rust_ffi_host produces all FFI variants.
324func RustFFIHostFactory() android.Module {
325	module, library := NewRustLibrary(android.HostSupported)
326	library.BuildOnlyFFI()
327	return module.Init()
328}
329
330// rust_library_dylib_host produces a dylib.
331func RustLibraryDylibHostFactory() android.Module {
332	module, library := NewRustLibrary(android.HostSupported)
333	library.BuildOnlyDylib()
334	return module.Init()
335}
336
337// rust_library_rlib_host produces an rlib.
338func RustLibraryRlibHostFactory() android.Module {
339	module, library := NewRustLibrary(android.HostSupported)
340	library.BuildOnlyRlib()
341	return module.Init()
342}
343
344// rust_ffi_static_host produces a static library.
345func RustFFIStaticHostFactory() android.Module {
346	module, library := NewRustLibrary(android.HostSupported)
347	library.BuildOnlyStatic()
348	return module.Init()
349}
350
351// rust_ffi_shared_host produces an shared library.
352func RustFFISharedHostFactory() android.Module {
353	module, library := NewRustLibrary(android.HostSupported)
354	library.BuildOnlyShared()
355	return module.Init()
356}
357
358func (library *libraryDecorator) BuildOnlyFFI() {
359	library.MutatedProperties.BuildDylib = false
360	library.MutatedProperties.BuildRlib = false
361	library.MutatedProperties.BuildShared = true
362	library.MutatedProperties.BuildStatic = true
363}
364
365func (library *libraryDecorator) BuildOnlyRust() {
366	library.MutatedProperties.BuildDylib = true
367	library.MutatedProperties.BuildRlib = true
368	library.MutatedProperties.BuildShared = false
369	library.MutatedProperties.BuildStatic = false
370}
371
372func (library *libraryDecorator) BuildOnlyDylib() {
373	library.MutatedProperties.BuildDylib = true
374	library.MutatedProperties.BuildRlib = false
375	library.MutatedProperties.BuildShared = false
376	library.MutatedProperties.BuildStatic = false
377}
378
379func (library *libraryDecorator) BuildOnlyRlib() {
380	library.MutatedProperties.BuildDylib = false
381	library.MutatedProperties.BuildRlib = true
382	library.MutatedProperties.BuildShared = false
383	library.MutatedProperties.BuildStatic = false
384}
385
386func (library *libraryDecorator) BuildOnlyStatic() {
387	library.MutatedProperties.BuildRlib = false
388	library.MutatedProperties.BuildDylib = false
389	library.MutatedProperties.BuildShared = false
390	library.MutatedProperties.BuildStatic = true
391}
392
393func (library *libraryDecorator) BuildOnlyShared() {
394	library.MutatedProperties.BuildRlib = false
395	library.MutatedProperties.BuildDylib = false
396	library.MutatedProperties.BuildStatic = false
397	library.MutatedProperties.BuildShared = true
398}
399
400func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
401	module := newModule(hod, android.MultilibBoth)
402
403	library := &libraryDecorator{
404		MutatedProperties: LibraryMutatedProperties{
405			BuildDylib:  false,
406			BuildRlib:   false,
407			BuildShared: false,
408			BuildStatic: false,
409		},
410		baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
411		flagExporter: NewFlagExporter(),
412	}
413
414	module.compiler = library
415
416	return module, library
417}
418
419func (library *libraryDecorator) compilerProps() []interface{} {
420	return append(library.baseCompiler.compilerProps(),
421		&library.Properties,
422		&library.MutatedProperties,
423		&library.stripper.StripProperties)
424}
425
426func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
427	deps = library.baseCompiler.compilerDeps(ctx, deps)
428
429	if library.dylib() || library.shared() {
430		if ctx.toolchain().Bionic() {
431			deps = bionicDeps(ctx, deps, false)
432			deps.CrtBegin = []string{"crtbegin_so"}
433			deps.CrtEnd = []string{"crtend_so"}
434		} else if ctx.Os() == android.LinuxMusl {
435			deps = muslDeps(ctx, deps, false)
436			deps.CrtBegin = []string{"libc_musl_crtbegin_so"}
437			deps.CrtEnd = []string{"libc_musl_crtend_so"}
438		}
439	}
440
441	return deps
442}
443
444func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string {
445	return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
446}
447
448func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags {
449	flags = library.baseCompiler.cfgFlags(ctx, flags)
450	if library.dylib() {
451		// We need to add a dependency on std in order to link crates as dylibs.
452		// The hack to add this dependency is guarded by the following cfg so
453		// that we don't force a dependency when it isn't needed.
454		library.baseCompiler.Properties.Cfgs = append(library.baseCompiler.Properties.Cfgs, "android_dylib")
455	}
456
457	flags.RustFlags = append(flags.RustFlags, library.baseCompiler.cfgsToFlags()...)
458	flags.RustdocFlags = append(flags.RustdocFlags, library.baseCompiler.cfgsToFlags()...)
459
460	return flags
461}
462
463func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
464	flags = library.baseCompiler.compilerFlags(ctx, flags)
465
466	flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
467	if library.shared() || library.static() {
468		library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
469	}
470	if library.shared() {
471		flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
472	}
473
474	return flags
475}
476
477func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
478	var outputFile, ret android.ModuleOutPath
479	var fileName string
480	srcPath := library.srcPath(ctx, deps)
481
482	if library.sourceProvider != nil {
483		deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
484	}
485
486	// Calculate output filename
487	if library.rlib() {
488		fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix()
489		outputFile = android.PathForModuleOut(ctx, fileName)
490		ret = outputFile
491	} else if library.dylib() {
492		fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix()
493		outputFile = android.PathForModuleOut(ctx, fileName)
494		ret = outputFile
495	} else if library.static() {
496		fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix()
497		outputFile = android.PathForModuleOut(ctx, fileName)
498		ret = outputFile
499	} else if library.shared() {
500		fileName = library.sharedLibFilename(ctx)
501		outputFile = android.PathForModuleOut(ctx, fileName)
502		ret = outputFile
503	}
504
505	if !library.rlib() && !library.static() && library.stripper.NeedsStrip(ctx) {
506		strippedOutputFile := outputFile
507		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
508		library.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile)
509
510		library.baseCompiler.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile)
511	}
512	library.baseCompiler.unstrippedOutputFile = outputFile
513
514	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
515	flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
516	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
517
518	if library.dylib() {
519		// We need prefer-dynamic for now to avoid linking in the static stdlib. See:
520		// https://github.com/rust-lang/rust/issues/19680
521		// https://github.com/rust-lang/rust/issues/34909
522		flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
523	}
524
525	// Call the appropriate builder for this library type
526	if library.rlib() {
527		TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile)
528	} else if library.dylib() {
529		TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile)
530	} else if library.static() {
531		TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile)
532	} else if library.shared() {
533		TransformSrctoShared(ctx, srcPath, deps, flags, outputFile)
534	}
535
536	if library.rlib() || library.dylib() {
537		library.flagExporter.exportLinkDirs(deps.linkDirs...)
538		library.flagExporter.exportLinkObjects(deps.linkObjects...)
539	}
540
541	if library.static() || library.shared() {
542		ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
543			IncludeDirs: library.includeDirs,
544		})
545	}
546
547	if library.shared() {
548		// Optimize out relinking against shared libraries whose interface hasn't changed by
549		// depending on a table of contents file instead of the library itself.
550		tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc")
551		library.tocFile = android.OptionalPathForPath(tocFile)
552		cc.TransformSharedObjectToToc(ctx, outputFile, tocFile)
553
554		ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
555			TableOfContents: android.OptionalPathForPath(tocFile),
556			SharedLibrary:   outputFile,
557			Target:          ctx.Target(),
558		})
559	}
560
561	if library.static() {
562		depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build()
563		ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{
564			StaticLibrary: outputFile,
565
566			TransitiveStaticLibrariesForOrdering: depSet,
567		})
568	}
569
570	library.flagExporter.setProvider(ctx)
571
572	return ret
573}
574
575func (library *libraryDecorator) srcPath(ctx ModuleContext, deps PathDeps) android.Path {
576	if library.sourceProvider != nil {
577		// Assume the first source from the source provider is the library entry point.
578		return library.sourceProvider.Srcs()[0]
579	} else {
580		path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
581		return path
582	}
583}
584
585func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags,
586	deps PathDeps) android.OptionalPath {
587	// rustdoc has builtin support for documenting config specific information
588	// regardless of the actual config it was given
589	// (https://doc.rust-lang.org/rustdoc/advanced-features.html#cfgdoc-documenting-platform-specific-or-feature-specific-information),
590	// so we generate the rustdoc for only the primary module so that we have a
591	// single set of docs to refer to.
592	if ctx.Module() != ctx.PrimaryModule() {
593		return android.OptionalPath{}
594	}
595
596	return android.OptionalPathForPath(Rustdoc(ctx, library.srcPath(ctx, deps),
597		deps, flags))
598}
599
600func (library *libraryDecorator) getStem(ctx ModuleContext) string {
601	stem := library.baseCompiler.getStemWithoutSuffix(ctx)
602	validateLibraryStem(ctx, stem, library.crateName())
603
604	return stem + String(library.baseCompiler.Properties.Suffix)
605}
606
607func (library *libraryDecorator) install(ctx ModuleContext) {
608	// Only shared and dylib variants make sense to install.
609	if library.shared() || library.dylib() {
610		library.baseCompiler.install(ctx)
611	}
612}
613
614func (library *libraryDecorator) Disabled() bool {
615	return library.MutatedProperties.VariantIsDisabled
616}
617
618func (library *libraryDecorator) SetDisabled() {
619	library.MutatedProperties.VariantIsDisabled = true
620}
621
622var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+")
623
624func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) {
625	if crate_name == "" {
626		ctx.PropertyErrorf("crate_name", "crate_name must be defined.")
627	}
628
629	// crate_names are used for the library output file, and rustc expects these
630	// to be alphanumeric with underscores allowed.
631	if validCrateName.MatchString(crate_name) {
632		ctx.PropertyErrorf("crate_name",
633			"library crate_names must be alphanumeric with underscores allowed")
634	}
635
636	// Libraries are expected to begin with "lib" followed by the crate_name
637	if !strings.HasPrefix(filename, "lib"+crate_name) {
638		ctx.ModuleErrorf("Invalid name or stem property; library filenames must start with lib<crate_name>")
639	}
640}
641
642// LibraryMutator mutates the libraries into variants according to the
643// build{Rlib,Dylib} attributes.
644func LibraryMutator(mctx android.BottomUpMutatorContext) {
645	// Only mutate on Rust libraries.
646	m, ok := mctx.Module().(*Module)
647	if !ok || m.compiler == nil {
648		return
649	}
650	library, ok := m.compiler.(libraryInterface)
651	if !ok {
652		return
653	}
654
655	var variants []string
656	// The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib)
657	// depend on this variant. It must be the first variant to be declared.
658	sourceVariant := false
659	if m.sourceProvider != nil {
660		variants = append(variants, "source")
661		sourceVariant = true
662	}
663	if library.buildRlib() {
664		variants = append(variants, rlibVariation)
665	}
666	if library.buildDylib() {
667		variants = append(variants, dylibVariation)
668	}
669
670	if len(variants) == 0 {
671		return
672	}
673	modules := mctx.CreateLocalVariations(variants...)
674
675	// The order of the variations (modules) matches the variant names provided. Iterate
676	// through the new variation modules and set their mutated properties.
677	for i, v := range modules {
678		switch variants[i] {
679		case rlibVariation:
680			v.(*Module).compiler.(libraryInterface).setRlib()
681		case dylibVariation:
682			v.(*Module).compiler.(libraryInterface).setDylib()
683			if v.(*Module).ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
684				// TODO(b/165791368)
685				// Disable dylib Vendor Ramdisk variations until we support these.
686				v.(*Module).Disable()
687			}
688
689			variation := v.(*Module).ModuleBase.ImageVariation().Variation
690			if strings.HasPrefix(variation, cc.VendorVariationPrefix) {
691				// TODO(b/204303985)
692				// Disable vendor dylibs until they are supported
693				v.(*Module).Disable()
694			}
695
696			if strings.HasPrefix(variation, cc.VendorVariationPrefix) &&
697				m.HasVendorVariant() &&
698				!snapshot.IsVendorProprietaryModule(mctx) &&
699				strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() {
700
701				// cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are
702				// produced for Dylibs; however, dylibs should not be enabled for boardVndkVersion for
703				// non-vendor proprietary modules.
704				v.(*Module).Disable()
705			}
706
707		case "source":
708			v.(*Module).compiler.(libraryInterface).setSource()
709			// The source variant does not produce any library.
710			// Disable the compilation steps.
711			v.(*Module).compiler.SetDisabled()
712		}
713	}
714
715	// If a source variant is created, add an inter-variant dependency
716	// between the other variants and the source variant.
717	if sourceVariant {
718		sv := modules[0]
719		for _, v := range modules[1:] {
720			if !v.Enabled() {
721				continue
722			}
723			mctx.AddInterVariantDependency(sourceDepTag, v, sv)
724		}
725		// Alias the source variation so it can be named directly in "srcs" properties.
726		mctx.AliasVariation("source")
727	}
728}
729
730func LibstdMutator(mctx android.BottomUpMutatorContext) {
731	if m, ok := mctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() {
732		switch library := m.compiler.(type) {
733		case libraryInterface:
734			// Only create a variant if a library is actually being built.
735			if library.rlib() && !library.sysroot() {
736				variants := []string{"rlib-std", "dylib-std"}
737				modules := mctx.CreateLocalVariations(variants...)
738
739				rlib := modules[0].(*Module)
740				dylib := modules[1].(*Module)
741				rlib.compiler.(libraryInterface).setRlibStd()
742				dylib.compiler.(libraryInterface).setDylibStd()
743				if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation ||
744					strings.HasPrefix(dylib.ModuleBase.ImageVariation().Variation, cc.VendorVariationPrefix) {
745					// TODO(b/165791368)
746					// Disable rlibs that link against dylib-std on vendor and vendor ramdisk variations until those dylib
747					// variants are properly supported.
748					dylib.Disable()
749				}
750				rlib.Properties.RustSubName += RlibStdlibSuffix
751				dylib.Properties.RustSubName += DylibStdlibSuffix
752			}
753		}
754	}
755}
756
757func (l *libraryDecorator) snapshotHeaders() android.Paths {
758	if l.collectedSnapshotHeaders == nil {
759		panic("snapshotHeaders() must be called after collectHeadersForSnapshot()")
760	}
761	return l.collectedSnapshotHeaders
762}
763
764// collectHeadersForSnapshot collects all exported headers from library.
765// It globs header files in the source tree for exported include directories,
766// and tracks generated header files separately.
767//
768// This is to be called from GenerateAndroidBuildActions, and then collected
769// header files can be retrieved by snapshotHeaders().
770func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext, deps PathDeps) {
771	ret := android.Paths{}
772
773	// Glob together the headers from the modules include_dirs property
774	for _, path := range android.CopyOfPaths(l.includeDirs) {
775		dir := path.String()
776		globDir := dir + "/**/*"
777		glob, err := ctx.GlobWithDeps(globDir, nil)
778		if err != nil {
779			ctx.ModuleErrorf("glob of %q failed: %s", globDir, err)
780			return
781		}
782
783		for _, header := range glob {
784			// Filter out only the files with extensions that are headers.
785			found := false
786			for _, ext := range cc.HeaderExts {
787				if strings.HasSuffix(header, ext) {
788					found = true
789					break
790				}
791			}
792			if !found {
793				continue
794			}
795			ret = append(ret, android.PathForSource(ctx, header))
796		}
797	}
798
799	// Glob together the headers from C dependencies as well, starting with non-generated headers.
800	ret = append(ret, cc.GlobHeadersForSnapshot(ctx, append(android.CopyOfPaths(deps.depIncludePaths), deps.depSystemIncludePaths...))...)
801
802	// Collect generated headers from C dependencies.
803	ret = append(ret, cc.GlobGeneratedHeadersForSnapshot(ctx, deps.depGeneratedHeaders)...)
804
805	// TODO(185577950): If support for generated headers is added, they need to be collected here as well.
806	l.collectedSnapshotHeaders = ret
807}
808