• 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	"android/soong/cc"
19	"errors"
20	"fmt"
21	"path/filepath"
22	"strings"
23
24	"github.com/google/blueprint/proptools"
25
26	"android/soong/android"
27	"android/soong/rust/config"
28)
29
30type RustLinkage int
31
32const (
33	DylibLinkage RustLinkage = iota
34	RlibLinkage
35)
36
37type compiler interface {
38	initialize(ctx ModuleContext)
39	compilerFlags(ctx ModuleContext, flags Flags) Flags
40	cfgFlags(ctx ModuleContext, flags Flags) Flags
41	featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags
42	baseCompilerProps() BaseCompilerProperties
43	compilerProps() []interface{}
44	compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput
45	compilerDeps(ctx DepsContext, deps Deps) Deps
46	crateName() string
47	edition() string
48	features(ctx android.ConfigurableEvaluatorContext, module *Module) []string
49	rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath
50	Thinlto() bool
51
52	// Output directory in which source-generated code from dependencies is
53	// copied. This is equivalent to Cargo's OUT_DIR variable.
54	cargoOutDir() android.OptionalPath
55
56	// cargoPkgVersion returns the value of the Cargo_pkg_version property.
57	cargoPkgVersion() string
58
59	// cargoEnvCompat returns whether Cargo environment variables should be used.
60	cargoEnvCompat() bool
61
62	inData() bool
63	install(ctx ModuleContext)
64	relativeInstallPath() string
65	everInstallable() bool
66
67	nativeCoverage() bool
68
69	Disabled() bool
70	SetDisabled()
71
72	stdLinkage(device bool) RustLinkage
73	noStdlibs() bool
74
75	unstrippedOutputFilePath() android.Path
76	strippedOutputFilePath() android.OptionalPath
77
78	checkedCrateRootPath() (android.Path, error)
79
80	Aliases() map[string]string
81
82	moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
83}
84
85func (compiler *baseCompiler) edition() string {
86	return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition)
87}
88
89func (compiler *baseCompiler) setNoStdlibs() {
90	compiler.Properties.No_stdlibs = proptools.BoolPtr(true)
91}
92
93func (compiler *baseCompiler) disableLints() {
94	compiler.Properties.Lints = proptools.StringPtr("none")
95}
96
97func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler {
98	return &baseCompiler{
99		Properties: BaseCompilerProperties{},
100		dir:        dir,
101		dir64:      dir64,
102		location:   location,
103	}
104}
105
106type installLocation int
107
108const (
109	InstallInSystem installLocation = 0
110	InstallInData                   = iota
111
112	incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\""
113	genSubDir             = "out/"
114)
115
116type BaseCompilerProperties struct {
117	// path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs).
118	// Only a single source file can be defined. Modules which generate source can be included by prefixing
119	// the module name with ":", for example ":libfoo_bindgen"
120	//
121	// If no source file is defined, a single generated source module can be defined to be used as the main source.
122	Srcs []string `android:"path,arch_variant"`
123
124	// Entry point that is passed to rustc to begin the compilation. E.g. main.rs or lib.rs.
125	// When this property is set,
126	//    * sandboxing is enabled for this module, and
127	//    * the srcs attribute is interpreted as a list of all source files potentially
128	//          used in compilation, including the entrypoint, and
129	//    * compile_data can be used to add additional files used in compilation that
130	//          not directly used as source files.
131	Crate_root *string `android:"path,arch_variant"`
132
133	// name of the lint set that should be used to validate this module.
134	//
135	// Possible values are "default" (for using a sensible set of lints
136	// depending on the module's location), "android" (for the strictest
137	// lint set that applies to all Android platform code), "vendor" (for
138	// a relaxed set) and "none" (for ignoring all lint warnings and
139	// errors). The default value is "default".
140	Lints *string
141
142	// flags to pass to rustc. To enable configuration options or features, use the "cfgs" or "features" properties.
143	Flags []string `android:"arch_variant"`
144
145	// flags to pass to the linker
146	Ld_flags []string `android:"arch_variant"`
147
148	// Rust crate dependencies to rename. Each entry should be a string of the form "dependencyname:alias".
149	//
150	// "dependencyname" here should be the name of the crate, not the Android module. This is
151	// equivalent to writing `alias = { package = "dependencyname" }` in a `Cargo.toml`.
152	Aliases []string
153
154	// list of rust rlib crate dependencies
155	Rlibs proptools.Configurable[[]string] `android:"arch_variant"`
156
157	// list of rust automatic crate dependencies.
158	// Rustlibs linkage is rlib for host targets and dylib for device targets.
159	Rustlibs proptools.Configurable[[]string] `android:"arch_variant"`
160
161	// list of rust proc_macro crate dependencies
162	Proc_macros proptools.Configurable[[]string] `android:"arch_variant"`
163
164	// list of C shared library dependencies
165	Shared_libs proptools.Configurable[[]string] `android:"arch_variant"`
166
167	// list of C static library dependencies. These dependencies do not normally propagate to dependents
168	// and may need to be redeclared. See whole_static_libs for bundling static dependencies into a library.
169	Static_libs proptools.Configurable[[]string] `android:"arch_variant"`
170
171	// Similar to static_libs, but will bundle the static library dependency into a library. This is helpful
172	// to avoid having to redeclare the dependency for dependents of this library, but in some cases may also
173	// result in bloat if multiple dependencies all include the same static library whole.
174	//
175	// The common use case for this is when the static library is unlikely to be a dependency of other modules to avoid
176	// having to redeclare the static library dependency for every dependent module.
177	// If you are not sure what to, for rust_library modules most static dependencies should go in static_libraries,
178	// and for rust_ffi modules most static dependencies should go into whole_static_libraries.
179	//
180	// For rust_ffi static variants, these libraries will be included in the resulting static library archive.
181	//
182	// For rust_library rlib variants, these libraries will be bundled into the resulting rlib library. This will
183	// include all of the static libraries symbols in any dylibs or binaries which use this rlib as well.
184	Whole_static_libs proptools.Configurable[[]string] `android:"arch_variant"`
185
186	// list of Rust system library dependencies.
187	//
188	// This is usually only needed when `no_stdlibs` is true, in which case it can be used to depend on system crates
189	// like `core` and `alloc`.
190	Stdlibs proptools.Configurable[[]string] `android:"arch_variant"`
191
192	// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
193	// modules which create library variants (rust_bindgen). This must be the expected extern crate name used in
194	// source, and is required to conform to an enforced format matching library output files (if the output file is
195	// lib<someName><suffix>, the crate_name property must be <someName>).
196	Crate_name string `android:"arch_variant"`
197
198	// list of features to enable for this crate
199	Features proptools.Configurable[[]string] `android:"arch_variant"`
200
201	// list of configuration options to enable for this crate. To enable features, use the "features" property.
202	Cfgs proptools.Configurable[[]string] `android:"arch_variant"`
203
204	// specific rust edition that should be used if the default version is not desired
205	Edition *string `android:"arch_variant"`
206
207	// sets name of the output
208	Stem *string `android:"arch_variant"`
209
210	// append to name of output
211	Suffix *string `android:"arch_variant"`
212
213	// install to a subdirectory of the default install path for the module
214	Relative_install_path *string `android:"arch_variant"`
215
216	// whether to suppress inclusion of standard crates - defaults to false
217	No_stdlibs *bool `android:"arch_variant"`
218
219	// Change the rustlibs linkage to select rlib linkage by default for device targets.
220	// Also link libstd as an rlib as well on device targets.
221	// Note: This is the default behavior for host targets.
222	//
223	// This is primarily meant for rust_binary and rust_ffi modules where the default
224	// linkage of libstd might need to be overridden in some use cases. This should
225	// generally be avoided with other module types since it may cause collisions at
226	// linkage if all dependencies of the root binary module do not link against libstd
227	// the same way.
228	Prefer_rlib *bool `android:"arch_variant"`
229
230	// Enables emitting certain Cargo environment variables. Only intended to be used for compatibility purposes.
231	// Will set CARGO_CRATE_NAME to the crate_name property's value.
232	// Will set CARGO_BIN_NAME to the output filename value without the extension.
233	Cargo_env_compat *bool
234
235	// If cargo_env_compat is true, sets the CARGO_PKG_VERSION env var to this value.
236	Cargo_pkg_version *string
237
238	// Control whether LTO is used for the final (Rust) linkage. This does not impact
239	// cross-language LTO.
240	Lto struct {
241		// Whether thin LTO should be enabled. By default this is true.
242		// LTO provides such a large code size benefit for Rust, this should always
243		// be enabled for production builds unless there's a clear need to disable it.
244		Thin *bool `android:"arch_variant"`
245	} `android:"arch_variant"`
246}
247
248type baseCompiler struct {
249	Properties BaseCompilerProperties
250
251	// Install related
252	dir      string
253	dir64    string
254	subDir   string
255	relative string
256	path     android.InstallPath
257	location installLocation
258	sanitize *sanitize
259
260	installDeps android.InstallPaths
261
262	// unstripped output file.
263	unstrippedOutputFile android.Path
264
265	// stripped output file.
266	strippedOutputFile android.OptionalPath
267
268	// If a crate has a source-generated dependency, a copy of the source file
269	// will be available in cargoOutDir (equivalent to Cargo OUT_DIR).
270	// This is stored internally because it may not be available during
271	// singleton-generation passes like rustdoc/rust_project.json, but should
272	// be stashed during initial generation.
273	cachedCargoOutDir android.ModuleOutPath
274	// Calculated crate root cached internally because ModuleContext is not
275	// available to singleton targets like rustdoc/rust_project.json
276	cachedCrateRootPath android.Path
277	// If cachedCrateRootPath is nil after initialization, this will contain
278	// an explanation of why
279	cachedCrateRootError error
280}
281
282func (compiler *baseCompiler) Disabled() bool {
283	return false
284}
285
286// Thin LTO is enabled by default.
287func (compiler *baseCompiler) Thinlto() bool {
288	return BoolDefault(compiler.Properties.Lto.Thin, true)
289}
290
291func (compiler *baseCompiler) SetDisabled() {
292	panic("baseCompiler does not implement SetDisabled()")
293}
294
295func (compiler *baseCompiler) noStdlibs() bool {
296	return Bool(compiler.Properties.No_stdlibs)
297}
298
299func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath {
300	panic("baseCompiler does not implement coverageOutputZipPath()")
301}
302
303func (compiler *baseCompiler) preferRlib() bool {
304	return Bool(compiler.Properties.Prefer_rlib)
305}
306
307func (compiler *baseCompiler) Aliases() map[string]string {
308	aliases := map[string]string{}
309	for _, entry := range compiler.Properties.Aliases {
310		dep, alias, found := strings.Cut(entry, ":")
311		if !found {
312			panic(fmt.Errorf("invalid aliases entry %q missing ':'", entry))
313		}
314		aliases[dep] = alias
315	}
316	return aliases
317}
318
319func (compiler *baseCompiler) stdLinkage(device bool) RustLinkage {
320	// For devices, we always link stdlibs in as dylibs by default.
321	if compiler.preferRlib() {
322		return RlibLinkage
323	} else if device {
324		return DylibLinkage
325	} else {
326		return RlibLinkage
327	}
328}
329
330func (compiler *baseCompiler) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
331	moduleInfoJSON.Class = []string{"ETC"}
332
333	mod := ctx.Module().(*Module)
334
335	moduleInfoJSON.SharedLibs = mod.transitiveAndroidMkSharedLibs.ToList()
336	moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.transitiveAndroidMkSharedLibs.ToList()...)
337	moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkDylibs...)
338	moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkHeaderLibs...)
339	moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkProcMacroLibs...)
340	moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkRlibs...)
341	moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkStaticLibs...)
342	moduleInfoJSON.SystemSharedLibs = []string{"none"}
343	moduleInfoJSON.StaticLibs = mod.Properties.AndroidMkStaticLibs
344
345	if mod.sourceProvider != nil {
346		moduleInfoJSON.SubName += mod.sourceProvider.getSubName()
347	}
348	moduleInfoJSON.SubName += mod.AndroidMkSuffix()
349
350	if mod.Properties.IsSdkVariant {
351		moduleInfoJSON.Uninstallable = true
352	}
353}
354
355var _ compiler = (*baseCompiler)(nil)
356
357func (compiler *baseCompiler) inData() bool {
358	return compiler.location == InstallInData
359}
360
361func (compiler *baseCompiler) compilerProps() []interface{} {
362	return []interface{}{&compiler.Properties}
363}
364
365func (compiler *baseCompiler) baseCompilerProps() BaseCompilerProperties {
366	return compiler.Properties
367}
368
369func cfgsToFlags(cfgs []string) []string {
370	flags := make([]string, 0, len(cfgs))
371	for _, cfg := range cfgs {
372		flags = append(flags, "--cfg '"+cfg+"'")
373	}
374
375	return flags
376}
377
378func (compiler *baseCompiler) features(ctx android.ConfigurableEvaluatorContext, module *Module) []string {
379	eval := module.ConfigurableEvaluator(ctx)
380	return compiler.Properties.Features.GetOrDefault(eval, nil)
381}
382
383func (compiler *baseCompiler) featuresToFlags(ctx android.ConfigurableEvaluatorContext, module *Module) []string {
384	flags := []string{}
385	for _, feature := range compiler.features(ctx, module) {
386		flags = append(flags, "--cfg 'feature=\""+feature+"\"'")
387	}
388
389	return flags
390}
391
392func (compiler *baseCompiler) featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags {
393	flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(ctx, module)...)
394	flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags(ctx, module)...)
395
396	return flags
397}
398
399func CommonDefaultCfgFlags(flags Flags, vendor bool, product bool) Flags {
400	var cfgs []string
401	if vendor || product {
402		cfgs = append(cfgs, "android_vndk")
403		if vendor {
404			cfgs = append(cfgs, "android_vendor")
405		} else if product {
406			cfgs = append(cfgs, "android_product")
407		}
408	}
409
410	flags.RustFlags = append(flags.RustFlags, cfgsToFlags(cfgs)...)
411	flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(cfgs)...)
412	return flags
413}
414
415func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags {
416	flags = CommonDefaultCfgFlags(flags, ctx.RustModule().InVendor(), ctx.RustModule().InProduct())
417
418	cfgFlags := cfgsToFlags(compiler.Properties.Cfgs.GetOrDefault(ctx, nil))
419	flags.RustFlags = append(flags.RustFlags, cfgFlags...)
420	flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...)
421
422	return flags
423}
424
425func CommonDefaultFlags(ctx android.ModuleContext, toolchain config.Toolchain, flags Flags) Flags {
426	flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
427	flags.GlobalRustFlags = append(flags.GlobalRustFlags, toolchain.ToolchainRustFlags())
428	flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, toolchain.ToolchainLinkFlags())
429	flags.EmitXrefs = ctx.Config().EmitXrefRules()
430
431	if ctx.Host() && !ctx.Windows() {
432		flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...)
433	}
434
435	if ctx.Os() == android.Linux {
436		// Add -lc, -lrt, -ldl, -lpthread, -lm and -lgcc_s to glibc builds to match
437		// the default behavior of device builds.
438		flags.LinkFlags = append(flags.LinkFlags, config.LinuxHostGlobalLinkFlags...)
439	} else if ctx.Os() == android.Darwin {
440		// Add -lc, -ldl, -lpthread and -lm to glibc darwin builds to match the default
441		// behavior of device builds.
442		flags.LinkFlags = append(flags.LinkFlags,
443			"-lc",
444			"-ldl",
445			"-lpthread",
446			"-lm",
447		)
448	}
449	return flags
450}
451
452func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {
453
454	flags = CommonDefaultFlags(ctx, ctx.toolchain(), flags)
455	lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints)
456	if err != nil {
457		ctx.PropertyErrorf("lints", err.Error())
458	}
459
460	// linkage-related flags are disallowed.
461	for _, s := range compiler.Properties.Ld_flags {
462		if strings.HasPrefix(s, "-Wl,-l") || strings.HasPrefix(s, "-Wl,-L") {
463			ctx.PropertyErrorf("ld_flags", "'-Wl,-l' and '-Wl,-L' flags cannot be manually specified")
464		}
465	}
466	for _, s := range compiler.Properties.Flags {
467		if strings.HasPrefix(s, "-l") || strings.HasPrefix(s, "-L") {
468			ctx.PropertyErrorf("flags", "'-l' and '-L' flags cannot be manually specified")
469		}
470		if strings.HasPrefix(s, "--extern") {
471			ctx.PropertyErrorf("flags", "'--extern' flag cannot be manually specified")
472		}
473		if strings.HasPrefix(s, "-Clink-args=") || strings.HasPrefix(s, "-C link-args=") {
474			ctx.PropertyErrorf("flags", "'-C link-args' flag cannot be manually specified")
475		}
476	}
477
478	flags.RustFlags = append(flags.RustFlags, lintFlags)
479	flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
480	flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition())
481	flags.RustdocFlags = append(flags.RustdocFlags, "--edition="+compiler.edition())
482	flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
483
484	return flags
485}
486
487func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
488	panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
489}
490
491func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags,
492	deps PathDeps) android.OptionalPath {
493
494	return android.OptionalPath{}
495}
496
497func (compiler *baseCompiler) initialize(ctx ModuleContext) {
498	compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir)
499	if compiler.Properties.Crate_root == nil {
500		compiler.cachedCrateRootPath, compiler.cachedCrateRootError = srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs)
501	} else {
502		compiler.cachedCrateRootPath = android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root)
503		compiler.cachedCrateRootError = nil
504	}
505}
506
507func (compiler *baseCompiler) cargoOutDir() android.OptionalPath {
508	return android.OptionalPathForPath(compiler.cachedCargoOutDir)
509}
510
511func (compiler *baseCompiler) cargoEnvCompat() bool {
512	return Bool(compiler.Properties.Cargo_env_compat)
513}
514
515func (compiler *baseCompiler) cargoPkgVersion() string {
516	return String(compiler.Properties.Cargo_pkg_version)
517}
518
519func (compiler *baseCompiler) unstrippedOutputFilePath() android.Path {
520	return compiler.unstrippedOutputFile
521}
522
523func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath {
524	return compiler.strippedOutputFile
525}
526
527func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
528	deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs.GetOrDefault(ctx, nil)...)
529	deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs.GetOrDefault(ctx, nil)...)
530	deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros.GetOrDefault(ctx, nil)...)
531	deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs.GetOrDefault(ctx, nil)...)
532	deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs.GetOrDefault(ctx, nil)...)
533	deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs.GetOrDefault(ctx, nil)...)
534	deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs.GetOrDefault(ctx, nil)...)
535
536	if !Bool(compiler.Properties.No_stdlibs) {
537		for _, stdlib := range config.Stdlibs {
538			// If we're building for the build host, use the prebuilt stdlibs, unless the host
539			// is linux_bionic which doesn't have prebuilts.
540			if ctx.Host() && !ctx.Target().HostCross && ctx.Target().Os != android.LinuxBionic {
541				stdlib = "prebuilt_" + stdlib
542			}
543			deps.Stdlibs = append(deps.Stdlibs, stdlib)
544		}
545	}
546	return deps
547}
548
549func bionicDeps(ctx DepsContext, deps Deps, static bool) Deps {
550	bionicLibs := []string{}
551	bionicLibs = append(bionicLibs, "liblog")
552	bionicLibs = append(bionicLibs, "libc")
553	bionicLibs = append(bionicLibs, "libm")
554	bionicLibs = append(bionicLibs, "libdl")
555
556	if static {
557		deps.StaticLibs = append(deps.StaticLibs, bionicLibs...)
558	} else {
559		deps.SharedLibs = append(deps.SharedLibs, bionicLibs...)
560	}
561	if ctx.RustModule().StaticExecutable() {
562		deps.StaticLibs = append(deps.StaticLibs, "libunwind")
563	}
564	if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" {
565		deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins)
566	}
567	return deps
568}
569
570func muslDeps(ctx DepsContext, deps Deps, static bool) Deps {
571	muslLibs := []string{"libc_musl"}
572	if static {
573		deps.StaticLibs = append(deps.StaticLibs, muslLibs...)
574	} else {
575		deps.SharedLibs = append(deps.SharedLibs, muslLibs...)
576	}
577	if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" {
578		deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins)
579	}
580
581	return deps
582}
583
584func (compiler *baseCompiler) crateName() string {
585	return compiler.Properties.Crate_name
586}
587
588func (compiler *baseCompiler) everInstallable() bool {
589	// Most modules are installable, so return true by default.
590	return true
591}
592
593func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath {
594	dir := compiler.dir
595	if ctx.toolchain().Is64Bit() && compiler.dir64 != "" {
596		dir = compiler.dir64
597	}
598	if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
599		dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath)
600	}
601	if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
602		dir = filepath.Join(dir, ctx.Arch().ArchType.String())
603	}
604
605	if compiler.location == InstallInData && ctx.RustModule().InVendorOrProduct() {
606		if ctx.RustModule().InProduct() {
607			dir = filepath.Join(dir, "product")
608		} else if ctx.RustModule().InVendor() {
609			dir = filepath.Join(dir, "vendor")
610		} else {
611			ctx.ModuleErrorf("Unknown data+VNDK installation kind")
612		}
613	}
614
615	return android.PathForModuleInstall(ctx, dir, compiler.subDir,
616		compiler.relativeInstallPath(), compiler.relative)
617}
618
619func (compiler *baseCompiler) nativeCoverage() bool {
620	return false
621}
622
623func (compiler *baseCompiler) install(ctx ModuleContext) {
624	path := ctx.RustModule().OutputFile()
625	compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path(), compiler.installDeps...)
626}
627
628func (compiler *baseCompiler) installTestData(ctx ModuleContext, data []android.DataPath) {
629	installedData := ctx.InstallTestData(compiler.installDir(ctx), data)
630	compiler.installDeps = append(compiler.installDeps, installedData...)
631}
632
633func (compiler *baseCompiler) getStem(ctx android.ModuleContext) string {
634	return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix)
635}
636
637func (compiler *baseCompiler) getStemWithoutSuffix(ctx android.BaseModuleContext) string {
638	stem := ctx.ModuleName()
639	if String(compiler.Properties.Stem) != "" {
640		stem = String(compiler.Properties.Stem)
641	}
642
643	return stem
644}
645
646func (compiler *baseCompiler) relativeInstallPath() string {
647	return String(compiler.Properties.Relative_install_path)
648}
649
650func (compiler *baseCompiler) checkedCrateRootPath() (android.Path, error) {
651	return compiler.cachedCrateRootPath, compiler.cachedCrateRootError
652}
653
654func crateRootPath(ctx ModuleContext, compiler compiler) android.Path {
655	root, err := compiler.checkedCrateRootPath()
656	if err != nil {
657		ctx.PropertyErrorf("srcs", err.Error())
658	}
659	return root
660}
661
662// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs.
663func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, error) {
664	// The srcs can contain strings with prefix ":".
665	// They are dependent modules of this module, with android.SourceDepTag.
666	// They are not the main source file compiled by rustc.
667	numSrcs := 0
668	srcIndex := 0
669	for i, s := range srcs {
670		if android.SrcIsModule(s) == "" {
671			numSrcs++
672			srcIndex = i
673		}
674	}
675	if numSrcs > 1 {
676		return nil, errors.New(incorrectSourcesError)
677	}
678
679	// If a main source file is not provided we expect only a single SourceProvider module to be defined
680	// within srcs, with the expectation that the first source it provides is the entry point.
681	if srcIndex != 0 {
682		return nil, errors.New("main source file must be the first in srcs")
683	} else if numSrcs > 1 {
684		return nil, errors.New("only a single generated source module can be defined without a main source file.")
685	}
686
687	// TODO: b/297264540 - once all modules are sandboxed, we need to select the proper
688	// entry point file from Srcs rather than taking the first one
689	paths := android.PathsForModuleSrc(ctx, srcs)
690	if len(paths) == 0 {
691		return nil, errors.New("srcs must not be empty")
692	}
693	return paths[srcIndex], nil
694}
695