• 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 {
250		panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName()))
251	}
252}
253
254func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
255	if ctx.RustModule().InVendor() {
256		// Vendor modules should statically link libstd.
257		return RlibLinkage
258	} else if library.static() || library.MutatedProperties.VariantIsStaticStd {
259		return RlibLinkage
260	} else if library.baseCompiler.preferRlib() {
261		return RlibLinkage
262	}
263	return DefaultLinkage
264}
265
266var _ compiler = (*libraryDecorator)(nil)
267var _ libraryInterface = (*libraryDecorator)(nil)
268var _ exportedFlagsProducer = (*libraryDecorator)(nil)
269
270// rust_library produces all Rust variants (rust_library_dylib and
271// rust_library_rlib).
272func RustLibraryFactory() android.Module {
273	module, library := NewRustLibrary(android.HostAndDeviceSupported)
274	library.BuildOnlyRust()
275	return module.Init()
276}
277
278// rust_ffi produces all FFI variants (rust_ffi_shared and
279// rust_ffi_static).
280func RustFFIFactory() android.Module {
281	module, library := NewRustLibrary(android.HostAndDeviceSupported)
282	library.BuildOnlyFFI()
283	return module.Init()
284}
285
286// rust_library_dylib produces a Rust dylib (Rust crate type "dylib").
287func RustLibraryDylibFactory() android.Module {
288	module, library := NewRustLibrary(android.HostAndDeviceSupported)
289	library.BuildOnlyDylib()
290	return module.Init()
291}
292
293// rust_library_rlib produces an rlib (Rust crate type "rlib").
294func RustLibraryRlibFactory() android.Module {
295	module, library := NewRustLibrary(android.HostAndDeviceSupported)
296	library.BuildOnlyRlib()
297	return module.Init()
298}
299
300// rust_ffi_shared produces a shared library (Rust crate type
301// "cdylib").
302func RustFFISharedFactory() android.Module {
303	module, library := NewRustLibrary(android.HostAndDeviceSupported)
304	library.BuildOnlyShared()
305	return module.Init()
306}
307
308// rust_ffi_static produces a static library (Rust crate type
309// "staticlib").
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 for the host
317// (rust_library_dylib_host and rust_library_rlib_host).
318func RustLibraryHostFactory() android.Module {
319	module, library := NewRustLibrary(android.HostSupported)
320	library.BuildOnlyRust()
321	return module.Init()
322}
323
324// rust_ffi_host produces all FFI variants for the host
325// (rust_ffi_static_host and rust_ffi_shared_host).
326func RustFFIHostFactory() android.Module {
327	module, library := NewRustLibrary(android.HostSupported)
328	library.BuildOnlyFFI()
329	return module.Init()
330}
331
332// rust_library_dylib_host produces a dylib for the host (Rust crate
333// type "dylib").
334func RustLibraryDylibHostFactory() android.Module {
335	module, library := NewRustLibrary(android.HostSupported)
336	library.BuildOnlyDylib()
337	return module.Init()
338}
339
340// rust_library_rlib_host produces an rlib for the host (Rust crate
341// type "rlib").
342func RustLibraryRlibHostFactory() android.Module {
343	module, library := NewRustLibrary(android.HostSupported)
344	library.BuildOnlyRlib()
345	return module.Init()
346}
347
348// rust_ffi_static_host produces a static library for the host (Rust
349// crate type "staticlib").
350func RustFFIStaticHostFactory() android.Module {
351	module, library := NewRustLibrary(android.HostSupported)
352	library.BuildOnlyStatic()
353	return module.Init()
354}
355
356// rust_ffi_shared_host produces an shared library for the host (Rust
357// crate type "cdylib").
358func RustFFISharedHostFactory() android.Module {
359	module, library := NewRustLibrary(android.HostSupported)
360	library.BuildOnlyShared()
361	return module.Init()
362}
363
364func (library *libraryDecorator) BuildOnlyFFI() {
365	library.MutatedProperties.BuildDylib = false
366	library.MutatedProperties.BuildRlib = false
367	library.MutatedProperties.BuildShared = true
368	library.MutatedProperties.BuildStatic = true
369}
370
371func (library *libraryDecorator) BuildOnlyRust() {
372	library.MutatedProperties.BuildDylib = true
373	library.MutatedProperties.BuildRlib = true
374	library.MutatedProperties.BuildShared = false
375	library.MutatedProperties.BuildStatic = false
376}
377
378func (library *libraryDecorator) BuildOnlyDylib() {
379	library.MutatedProperties.BuildDylib = true
380	library.MutatedProperties.BuildRlib = false
381	library.MutatedProperties.BuildShared = false
382	library.MutatedProperties.BuildStatic = false
383}
384
385func (library *libraryDecorator) BuildOnlyRlib() {
386	library.MutatedProperties.BuildDylib = false
387	library.MutatedProperties.BuildRlib = true
388	library.MutatedProperties.BuildShared = false
389	library.MutatedProperties.BuildStatic = false
390}
391
392func (library *libraryDecorator) BuildOnlyStatic() {
393	library.MutatedProperties.BuildRlib = false
394	library.MutatedProperties.BuildDylib = false
395	library.MutatedProperties.BuildShared = false
396	library.MutatedProperties.BuildStatic = true
397}
398
399func (library *libraryDecorator) BuildOnlyShared() {
400	library.MutatedProperties.BuildRlib = false
401	library.MutatedProperties.BuildDylib = false
402	library.MutatedProperties.BuildStatic = false
403	library.MutatedProperties.BuildShared = true
404}
405
406func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
407	module := newModule(hod, android.MultilibBoth)
408
409	library := &libraryDecorator{
410		MutatedProperties: LibraryMutatedProperties{
411			BuildDylib:  false,
412			BuildRlib:   false,
413			BuildShared: false,
414			BuildStatic: false,
415		},
416		baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
417		flagExporter: NewFlagExporter(),
418	}
419
420	module.compiler = library
421
422	return module, library
423}
424
425func (library *libraryDecorator) compilerProps() []interface{} {
426	return append(library.baseCompiler.compilerProps(),
427		&library.Properties,
428		&library.MutatedProperties,
429		&library.stripper.StripProperties)
430}
431
432func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
433	deps = library.baseCompiler.compilerDeps(ctx, deps)
434
435	if library.dylib() || library.shared() {
436		if ctx.toolchain().Bionic() {
437			deps = bionicDeps(ctx, deps, false)
438			deps.CrtBegin = []string{"crtbegin_so"}
439			deps.CrtEnd = []string{"crtend_so"}
440		} else if ctx.Os() == android.LinuxMusl {
441			deps = muslDeps(ctx, deps, false)
442			deps.CrtBegin = []string{"libc_musl_crtbegin_so"}
443			deps.CrtEnd = []string{"libc_musl_crtend_so"}
444		}
445	}
446
447	return deps
448}
449
450func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string {
451	return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
452}
453
454func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags {
455	flags = library.baseCompiler.cfgFlags(ctx, flags)
456	if library.dylib() {
457		// We need to add a dependency on std in order to link crates as dylibs.
458		// The hack to add this dependency is guarded by the following cfg so
459		// that we don't force a dependency when it isn't needed.
460		library.baseCompiler.Properties.Cfgs = append(library.baseCompiler.Properties.Cfgs, "android_dylib")
461	}
462
463	flags.RustFlags = append(flags.RustFlags, library.baseCompiler.cfgsToFlags()...)
464	flags.RustdocFlags = append(flags.RustdocFlags, library.baseCompiler.cfgsToFlags()...)
465
466	return flags
467}
468
469func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
470	flags = library.baseCompiler.compilerFlags(ctx, flags)
471
472	flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
473	if library.shared() || library.static() {
474		library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
475	}
476	if library.shared() {
477		flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
478	}
479
480	return flags
481}
482
483func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
484	var outputFile android.ModuleOutPath
485	var ret buildOutput
486	var fileName string
487	srcPath := library.srcPath(ctx, deps)
488
489	if library.sourceProvider != nil {
490		deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
491	}
492
493	// Calculate output filename
494	if library.rlib() {
495		fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix()
496		outputFile = android.PathForModuleOut(ctx, fileName)
497		ret.outputFile = outputFile
498	} else if library.dylib() {
499		fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix()
500		outputFile = android.PathForModuleOut(ctx, fileName)
501		ret.outputFile = outputFile
502	} else if library.static() {
503		fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix()
504		outputFile = android.PathForModuleOut(ctx, fileName)
505		ret.outputFile = outputFile
506	} else if library.shared() {
507		fileName = library.sharedLibFilename(ctx)
508		outputFile = android.PathForModuleOut(ctx, fileName)
509		ret.outputFile = outputFile
510	}
511
512	if !library.rlib() && !library.static() && library.stripper.NeedsStrip(ctx) {
513		strippedOutputFile := outputFile
514		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
515		library.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile)
516
517		library.baseCompiler.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile)
518	}
519	library.baseCompiler.unstrippedOutputFile = outputFile
520
521	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
522	flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
523	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects.Strings()...)
524
525	if library.dylib() {
526		// We need prefer-dynamic for now to avoid linking in the static stdlib. See:
527		// https://github.com/rust-lang/rust/issues/19680
528		// https://github.com/rust-lang/rust/issues/34909
529		flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
530	}
531
532	// Call the appropriate builder for this library type
533	if library.rlib() {
534		ret.kytheFile = TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile).kytheFile
535	} else if library.dylib() {
536		ret.kytheFile = TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile).kytheFile
537	} else if library.static() {
538		ret.kytheFile = TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile).kytheFile
539	} else if library.shared() {
540		ret.kytheFile = TransformSrctoShared(ctx, srcPath, deps, flags, outputFile).kytheFile
541	}
542
543	if library.rlib() || library.dylib() {
544		library.flagExporter.exportLinkDirs(deps.linkDirs...)
545		library.flagExporter.exportLinkObjects(deps.linkObjects...)
546		library.flagExporter.exportLibDeps(deps.LibDeps...)
547	}
548
549	if library.static() || library.shared() {
550		ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
551			IncludeDirs: library.includeDirs,
552		})
553	}
554
555	if library.shared() {
556		// Optimize out relinking against shared libraries whose interface hasn't changed by
557		// depending on a table of contents file instead of the library itself.
558		tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc")
559		library.tocFile = android.OptionalPathForPath(tocFile)
560		cc.TransformSharedObjectToToc(ctx, outputFile, tocFile)
561
562		ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
563			TableOfContents: android.OptionalPathForPath(tocFile),
564			SharedLibrary:   outputFile,
565			Target:          ctx.Target(),
566		})
567	}
568
569	if library.static() {
570		depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build()
571		ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{
572			StaticLibrary: outputFile,
573
574			TransitiveStaticLibrariesForOrdering: depSet,
575		})
576	}
577
578	library.flagExporter.setProvider(ctx)
579
580	return ret
581}
582
583func (library *libraryDecorator) srcPath(ctx ModuleContext, _ PathDeps) android.Path {
584	if library.sourceProvider != nil {
585		// Assume the first source from the source provider is the library entry point.
586		return library.sourceProvider.Srcs()[0]
587	} else {
588		path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
589		return path
590	}
591}
592
593func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags,
594	deps PathDeps) android.OptionalPath {
595	// rustdoc has builtin support for documenting config specific information
596	// regardless of the actual config it was given
597	// (https://doc.rust-lang.org/rustdoc/advanced-features.html#cfgdoc-documenting-platform-specific-or-feature-specific-information),
598	// so we generate the rustdoc for only the primary module so that we have a
599	// single set of docs to refer to.
600	if ctx.Module() != ctx.PrimaryModule() {
601		return android.OptionalPath{}
602	}
603
604	return android.OptionalPathForPath(Rustdoc(ctx, library.srcPath(ctx, deps),
605		deps, flags))
606}
607
608func (library *libraryDecorator) getStem(ctx ModuleContext) string {
609	stem := library.baseCompiler.getStemWithoutSuffix(ctx)
610	validateLibraryStem(ctx, stem, library.crateName())
611
612	return stem + String(library.baseCompiler.Properties.Suffix)
613}
614
615func (library *libraryDecorator) install(ctx ModuleContext) {
616	// Only shared and dylib variants make sense to install.
617	if library.shared() || library.dylib() {
618		library.baseCompiler.install(ctx)
619	}
620}
621
622func (library *libraryDecorator) Disabled() bool {
623	return library.MutatedProperties.VariantIsDisabled
624}
625
626func (library *libraryDecorator) SetDisabled() {
627	library.MutatedProperties.VariantIsDisabled = true
628}
629
630var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+")
631
632func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) {
633	if crate_name == "" {
634		ctx.PropertyErrorf("crate_name", "crate_name must be defined.")
635	}
636
637	// crate_names are used for the library output file, and rustc expects these
638	// to be alphanumeric with underscores allowed.
639	if validCrateName.MatchString(crate_name) {
640		ctx.PropertyErrorf("crate_name",
641			"library crate_names must be alphanumeric with underscores allowed")
642	}
643
644	// Libraries are expected to begin with "lib" followed by the crate_name
645	if !strings.HasPrefix(filename, "lib"+crate_name) {
646		ctx.ModuleErrorf("Invalid name or stem property; library filenames must start with lib<crate_name>")
647	}
648}
649
650// LibraryMutator mutates the libraries into variants according to the
651// build{Rlib,Dylib} attributes.
652func LibraryMutator(mctx android.BottomUpMutatorContext) {
653	// Only mutate on Rust libraries.
654	m, ok := mctx.Module().(*Module)
655	if !ok || m.compiler == nil {
656		return
657	}
658	library, ok := m.compiler.(libraryInterface)
659	if !ok {
660		return
661	}
662
663	var variants []string
664	// The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib)
665	// depend on this variant. It must be the first variant to be declared.
666	sourceVariant := false
667	if m.sourceProvider != nil {
668		variants = append(variants, "source")
669		sourceVariant = true
670	}
671	if library.buildRlib() {
672		variants = append(variants, rlibVariation)
673	}
674	if library.buildDylib() {
675		variants = append(variants, dylibVariation)
676	}
677
678	if len(variants) == 0 {
679		return
680	}
681	modules := mctx.CreateLocalVariations(variants...)
682
683	// The order of the variations (modules) matches the variant names provided. Iterate
684	// through the new variation modules and set their mutated properties.
685	for i, v := range modules {
686		switch variants[i] {
687		case rlibVariation:
688			v.(*Module).compiler.(libraryInterface).setRlib()
689		case dylibVariation:
690			v.(*Module).compiler.(libraryInterface).setDylib()
691			if v.(*Module).ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
692				// TODO(b/165791368)
693				// Disable dylib Vendor Ramdisk variations until we support these.
694				v.(*Module).Disable()
695			}
696
697			variation := v.(*Module).ModuleBase.ImageVariation().Variation
698			if strings.HasPrefix(variation, cc.VendorVariationPrefix) {
699				// TODO(b/204303985)
700				// Disable vendor dylibs until they are supported
701				v.(*Module).Disable()
702			}
703
704			if strings.HasPrefix(variation, cc.VendorVariationPrefix) &&
705				m.HasVendorVariant() &&
706				!snapshot.IsVendorProprietaryModule(mctx) &&
707				strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() {
708
709				// cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are
710				// produced for Dylibs; however, dylibs should not be enabled for boardVndkVersion for
711				// non-vendor proprietary modules.
712				v.(*Module).Disable()
713			}
714
715		case "source":
716			v.(*Module).compiler.(libraryInterface).setSource()
717			// The source variant does not produce any library.
718			// Disable the compilation steps.
719			v.(*Module).compiler.SetDisabled()
720		}
721	}
722
723	// If a source variant is created, add an inter-variant dependency
724	// between the other variants and the source variant.
725	if sourceVariant {
726		sv := modules[0]
727		for _, v := range modules[1:] {
728			if !v.Enabled() {
729				continue
730			}
731			mctx.AddInterVariantDependency(sourceDepTag, v, sv)
732		}
733		// Alias the source variation so it can be named directly in "srcs" properties.
734		mctx.AliasVariation("source")
735	}
736}
737
738func LibstdMutator(mctx android.BottomUpMutatorContext) {
739	if m, ok := mctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() {
740		switch library := m.compiler.(type) {
741		case libraryInterface:
742			// Only create a variant if a library is actually being built.
743			if library.rlib() && !library.sysroot() {
744				variants := []string{"rlib-std", "dylib-std"}
745				modules := mctx.CreateLocalVariations(variants...)
746
747				rlib := modules[0].(*Module)
748				dylib := modules[1].(*Module)
749				rlib.compiler.(libraryInterface).setRlibStd()
750				dylib.compiler.(libraryInterface).setDylibStd()
751				if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation ||
752					strings.HasPrefix(dylib.ModuleBase.ImageVariation().Variation, cc.VendorVariationPrefix) {
753					// TODO(b/165791368)
754					// Disable rlibs that link against dylib-std on vendor and vendor ramdisk variations until those dylib
755					// variants are properly supported.
756					dylib.Disable()
757				}
758				rlib.Properties.RustSubName += RlibStdlibSuffix
759				dylib.Properties.RustSubName += DylibStdlibSuffix
760			}
761		}
762	}
763}
764
765func (l *libraryDecorator) snapshotHeaders() android.Paths {
766	if l.collectedSnapshotHeaders == nil {
767		panic("snapshotHeaders() must be called after collectHeadersForSnapshot()")
768	}
769	return l.collectedSnapshotHeaders
770}
771
772// collectHeadersForSnapshot collects all exported headers from library.
773// It globs header files in the source tree for exported include directories,
774// and tracks generated header files separately.
775//
776// This is to be called from GenerateAndroidBuildActions, and then collected
777// header files can be retrieved by snapshotHeaders().
778func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext, deps PathDeps) {
779	ret := android.Paths{}
780
781	// Glob together the headers from the modules include_dirs property
782	for _, path := range android.CopyOfPaths(l.includeDirs) {
783		dir := path.String()
784		globDir := dir + "/**/*"
785		glob, err := ctx.GlobWithDeps(globDir, nil)
786		if err != nil {
787			ctx.ModuleErrorf("glob of %q failed: %s", globDir, err)
788			return
789		}
790
791		for _, header := range glob {
792			// Filter out only the files with extensions that are headers.
793			found := false
794			for _, ext := range cc.HeaderExts {
795				if strings.HasSuffix(header, ext) {
796					found = true
797					break
798				}
799			}
800			if !found {
801				continue
802			}
803			ret = append(ret, android.PathForSource(ctx, header))
804		}
805	}
806
807	// Glob together the headers from C dependencies as well, starting with non-generated headers.
808	ret = append(ret, cc.GlobHeadersForSnapshot(ctx, append(android.CopyOfPaths(deps.depIncludePaths), deps.depSystemIncludePaths...))...)
809
810	// Collect generated headers from C dependencies.
811	ret = append(ret, cc.GlobGeneratedHeadersForSnapshot(ctx, deps.depGeneratedHeaders)...)
812
813	// TODO(185577950): If support for generated headers is added, they need to be collected here as well.
814	l.collectedSnapshotHeaders = ret
815}
816