• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package sh
16
17import (
18	"fmt"
19	"path/filepath"
20	"strings"
21
22	"github.com/google/blueprint"
23	"github.com/google/blueprint/proptools"
24
25	"android/soong/android"
26	"android/soong/cc"
27	"android/soong/tradefed"
28)
29
30// sh_binary is for shell scripts (and batch files) that are installed as
31// executable files into .../bin/
32//
33// Do not use them for prebuilt C/C++/etc files.  Use cc_prebuilt_binary
34// instead.
35
36var pctx = android.NewPackageContext("android/soong/sh")
37
38func init() {
39	pctx.Import("android/soong/android")
40
41	registerShBuildComponents(android.InitRegistrationContext)
42}
43
44type ShBinaryInfo struct {
45	SubDir     string
46	OutputFile android.Path
47	Symlinks   []string
48}
49
50var ShBinaryInfoProvider = blueprint.NewProvider[ShBinaryInfo]()
51
52func registerShBuildComponents(ctx android.RegistrationContext) {
53	ctx.RegisterModuleType("sh_binary", ShBinaryFactory)
54	ctx.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
55	ctx.RegisterModuleType("sh_test", ShTestFactory)
56	ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
57	ctx.RegisterModuleType("sh_defaults", ShDefaultsFactory)
58}
59
60// Test fixture preparer that will register most sh build components.
61//
62// Singletons and mutators should only be added here if they are needed for a majority of sh
63// module types, otherwise they should be added under a separate preparer to allow them to be
64// selected only when needed to reduce test execution time.
65//
66// Module types do not have much of an overhead unless they are used so this should include as many
67// module types as possible. The exceptions are those module types that require mutators and/or
68// singletons in order to function in which case they should be kept together in a separate
69// preparer.
70var PrepareForTestWithShBuildComponents = android.GroupFixturePreparers(
71	android.FixtureRegisterWithContext(registerShBuildComponents),
72)
73
74type shBinaryProperties struct {
75	// Source file of this prebuilt.
76	Src *string `android:"path,arch_variant"`
77
78	// optional subdirectory under which this file is installed into
79	Sub_dir *string `android:"arch_variant"`
80
81	// optional name for the installed file. If unspecified, name of the module is used as the file name
82	Filename *string `android:"arch_variant"`
83
84	// when set to true, and filename property is not set, the name for the installed file
85	// is the same as the file name of the source file.
86	Filename_from_src *bool `android:"arch_variant"`
87
88	// Whether this module is directly installable to one of the partitions. Default: true.
89	Installable *bool
90
91	// install symlinks to the binary
92	Symlinks []string `android:"arch_variant"`
93
94	// Make this module available when building for ramdisk.
95	// On device without a dedicated recovery partition, the module is only
96	// available after switching root into
97	// /first_stage_ramdisk. To expose the module before switching root, install
98	// the recovery variant instead.
99	Ramdisk_available *bool
100
101	// Make this module available when building for vendor ramdisk.
102	// On device without a dedicated recovery partition, the module is only
103	// available after switching root into
104	// /first_stage_ramdisk. To expose the module before switching root, install
105	// the recovery variant instead.
106	Vendor_ramdisk_available *bool
107
108	// Make this module available when building for recovery.
109	Recovery_available *bool
110
111	// The name of the image this module is built for
112	ImageVariation string `blueprint:"mutated"`
113
114	// Suffix for the name of Android.mk entries generated by this module
115	SubName string `blueprint:"mutated"`
116}
117
118type TestProperties struct {
119	// list of compatibility suites (for example "cts", "vts") that the module should be
120	// installed into.
121	Test_suites []string `android:"arch_variant"`
122
123	// the name of the test configuration (for example "AndroidTest.xml") that should be
124	// installed with the module.
125	Test_config *string `android:"path,arch_variant"`
126
127	// list of files or filegroup modules that provide data that should be installed alongside
128	// the test.
129	Data []string `android:"path,arch_variant"`
130
131	// same as data, but adds dependencies using the device's os variation and the common
132	// architecture's variation. Can be used to add a module built for device to the data of a
133	// host test.
134	Device_common_data []string `android:"path_device_common"`
135
136	// same as data, but adds dependencies using the device's os variation and the device's first
137	// architecture's variation. Can be used to add a module built for device to the data of a
138	// host test.
139	Device_first_data []string `android:"path_device_first"`
140
141	// Same as data, but will add dependencies on modules using the host's os variation and
142	// the common arch variation. Useful for a device test that wants to depend on a host
143	// module, for example to include a custom Tradefed test runner.
144	Host_common_data []string `android:"path_host_common"`
145
146	// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
147	// with root permission.
148	Require_root *bool
149
150	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
151	// should be installed with the module.
152	Test_config_template *string `android:"path,arch_variant"`
153
154	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
155	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
156	// explicitly.
157	Auto_gen_config *bool
158
159	// list of binary modules that should be installed alongside the test
160	Data_bins []string `android:"path,arch_variant"`
161
162	// list of library modules that should be installed alongside the test
163	Data_libs []string `android:"path,arch_variant"`
164
165	// list of device binary modules that should be installed alongside the test.
166	// Only available for host sh_test modules.
167	Data_device_bins []string `android:"path,arch_variant"`
168
169	// list of device library modules that should be installed alongside the test.
170	// Only available for host sh_test modules.
171	Data_device_libs []string `android:"path,arch_variant"`
172
173	// list of java modules that provide data that should be installed alongside the test.
174	Java_data []string
175
176	// Install the test into a folder named for the module in all test suites.
177	Per_testcase_directory *bool
178
179	// Test options.
180	Test_options android.CommonTestOptions
181
182	// a list of extra test configuration files that should be installed with the module.
183	Extra_test_configs []string `android:"path,arch_variant"`
184}
185
186type ShBinary struct {
187	android.ModuleBase
188	android.DefaultableModuleBase
189
190	properties shBinaryProperties
191
192	sourceFilePath android.Path
193	outputFilePath android.OutputPath
194	installedFile  android.InstallPath
195}
196
197var _ android.HostToolProvider = (*ShBinary)(nil)
198
199type ShTest struct {
200	ShBinary
201
202	testProperties TestProperties
203
204	installDir android.InstallPath
205
206	data             []android.DataPath
207	testConfig       android.Path
208	extraTestConfigs android.Paths
209
210	dataModules map[string]android.Path
211}
212
213func (s *ShBinary) HostToolPath() android.OptionalPath {
214	return android.OptionalPathForPath(s.installedFile)
215}
216
217func (s *ShBinary) DepsMutator(ctx android.BottomUpMutatorContext) {
218}
219
220func (s *ShBinary) OutputFile() android.Path {
221	return s.outputFilePath
222}
223
224func (s *ShBinary) SubDir() string {
225	return proptools.String(s.properties.Sub_dir)
226}
227
228func (s *ShBinary) RelativeInstallPath() string {
229	return s.SubDir()
230}
231func (s *ShBinary) Installable() bool {
232	return s.properties.Installable == nil || proptools.Bool(s.properties.Installable)
233}
234
235func (s *ShBinary) Symlinks() []string {
236	return s.properties.Symlinks
237}
238
239var _ android.ImageInterface = (*ShBinary)(nil)
240
241func (s *ShBinary) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
242
243func (s *ShBinary) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
244	return s.InstallInVendor()
245}
246
247func (s *ShBinary) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
248	return s.InstallInProduct()
249}
250
251func (s *ShBinary) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
252	return !s.InstallInRecovery() && !s.InstallInRamdisk() && !s.InstallInVendorRamdisk() && !s.ModuleBase.InstallInVendor()
253}
254
255func (s *ShBinary) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
256	return proptools.Bool(s.properties.Ramdisk_available) || s.InstallInRamdisk()
257}
258
259func (s *ShBinary) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
260	return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.InstallInVendorRamdisk()
261}
262
263func (s *ShBinary) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
264	return false
265}
266
267func (s *ShBinary) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
268	return proptools.Bool(s.properties.Recovery_available) || s.InstallInRecovery()
269}
270
271func (s *ShBinary) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
272	return nil
273}
274
275func (s *ShBinary) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
276	s.properties.ImageVariation = variation
277}
278
279// Overrides ModuleBase.InstallInRamdisk() so that the install rule respects
280// Ramdisk_available property for ramdisk variant
281func (s *ShBinary) InstallInRamdisk() bool {
282	return s.ModuleBase.InstallInRamdisk() ||
283		(proptools.Bool(s.properties.Ramdisk_available) && s.properties.ImageVariation == android.RamdiskVariation)
284}
285
286// Overrides ModuleBase.InstallInVendorRamdisk() so that the install rule respects
287// Vendor_ramdisk_available property for vendor ramdisk variant
288func (s *ShBinary) InstallInVendorRamdisk() bool {
289	return s.ModuleBase.InstallInVendorRamdisk() ||
290		(proptools.Bool(s.properties.Vendor_ramdisk_available) && s.properties.ImageVariation == android.VendorRamdiskVariation)
291}
292
293// Overrides ModuleBase.InstallInRecovery() so that the install rule respects
294// Recovery_available property for recovery variant
295func (s *ShBinary) InstallInRecovery() bool {
296	return s.ModuleBase.InstallInRecovery() ||
297		(proptools.Bool(s.properties.Recovery_available) && s.properties.ImageVariation == android.RecoveryVariation)
298}
299
300func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
301	if s.properties.Src == nil {
302		ctx.PropertyErrorf("src", "missing prebuilt source file")
303	}
304
305	s.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(s.properties.Src))
306	filename := proptools.String(s.properties.Filename)
307	filenameFromSrc := proptools.Bool(s.properties.Filename_from_src)
308	if filename == "" {
309		if filenameFromSrc {
310			filename = s.sourceFilePath.Base()
311		} else {
312			filename = ctx.ModuleName()
313		}
314	} else if filenameFromSrc {
315		ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
316		return
317	}
318	s.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
319
320	// This ensures that outputFilePath has the correct name for others to
321	// use, as the source file may have a different name.
322	ctx.Build(pctx, android.BuildParams{
323		Rule:   android.CpExecutable,
324		Output: s.outputFilePath,
325		Input:  s.sourceFilePath,
326	})
327
328	s.properties.SubName = s.GetSubname(ctx)
329
330	android.SetProvider(ctx, ShBinaryInfoProvider, ShBinaryInfo{
331		SubDir:     s.SubDir(),
332		OutputFile: s.OutputFile(),
333		Symlinks:   s.Symlinks(),
334	})
335
336	ctx.SetOutputFiles(android.Paths{s.outputFilePath}, "")
337}
338
339func (s *ShBinary) GetSubname(ctx android.ModuleContext) string {
340	ret := ""
341	if s.properties.ImageVariation != "" {
342		if s.properties.ImageVariation != android.VendorVariation {
343			ret = "." + s.properties.ImageVariation
344		}
345	}
346	return ret
347}
348
349func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
350	s.generateAndroidBuildActions(ctx)
351	installDir := android.PathForModuleInstall(ctx, "bin", proptools.String(s.properties.Sub_dir))
352	if !s.Installable() {
353		s.SkipInstall()
354	}
355	s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
356	for _, symlink := range s.Symlinks() {
357		ctx.InstallSymlink(installDir, symlink, s.installedFile)
358	}
359	moduleInfoJSON := ctx.ModuleInfoJSON()
360	moduleInfoJSON.Class = []string{"EXECUTABLES"}
361}
362
363func (s *ShBinary) AndroidMkEntries() []android.AndroidMkEntries {
364	return []android.AndroidMkEntries{{
365		Class:      "EXECUTABLES",
366		OutputFile: android.OptionalPathForPath(s.outputFilePath),
367		Include:    "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
368		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
369			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
370				s.customAndroidMkEntries(entries)
371				entries.SetString("LOCAL_MODULE_RELATIVE_PATH", proptools.String(s.properties.Sub_dir))
372				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !s.Installable())
373			},
374		},
375		SubName: s.properties.SubName,
376	}}
377}
378
379func (s *ShBinary) customAndroidMkEntries(entries *android.AndroidMkEntries) {
380	entries.SetString("LOCAL_MODULE_SUFFIX", "")
381	entries.SetString("LOCAL_MODULE_STEM", s.outputFilePath.Rel())
382	if len(s.properties.Symlinks) > 0 {
383		entries.SetString("LOCAL_MODULE_SYMLINKS", strings.Join(s.properties.Symlinks, " "))
384	}
385}
386
387type dependencyTag struct {
388	blueprint.BaseDependencyTag
389	name string
390}
391
392var (
393	shTestDataBinsTag       = dependencyTag{name: "dataBins"}
394	shTestDataLibsTag       = dependencyTag{name: "dataLibs"}
395	shTestDataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
396	shTestDataDeviceLibsTag = dependencyTag{name: "dataDeviceLibs"}
397	shTestJavaDataTag       = dependencyTag{name: "javaData"}
398)
399
400var sharedLibVariations = []blueprint.Variation{{Mutator: "link", Variation: "shared"}}
401
402func (s *ShTest) DepsMutator(ctx android.BottomUpMutatorContext) {
403	s.ShBinary.DepsMutator(ctx)
404
405	ctx.AddFarVariationDependencies(ctx.Target().Variations(), shTestDataBinsTag, s.testProperties.Data_bins...)
406	ctx.AddFarVariationDependencies(append(ctx.Target().Variations(), sharedLibVariations...),
407		shTestDataLibsTag, s.testProperties.Data_libs...)
408	if ctx.Target().Os.Class == android.Host && len(ctx.Config().Targets[android.Android]) > 0 {
409		deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
410		ctx.AddFarVariationDependencies(deviceVariations, shTestDataDeviceBinsTag, s.testProperties.Data_device_bins...)
411		ctx.AddFarVariationDependencies(append(deviceVariations, sharedLibVariations...),
412			shTestDataDeviceLibsTag, s.testProperties.Data_device_libs...)
413
414		javaDataVariation := []blueprint.Variation{{"arch", android.Common.String()}}
415		ctx.AddVariationDependencies(javaDataVariation, shTestJavaDataTag, s.testProperties.Java_data...)
416
417	} else if ctx.Target().Os.Class != android.Host {
418		if len(s.testProperties.Data_device_bins) > 0 {
419			ctx.PropertyErrorf("data_device_bins", "only available for host modules")
420		}
421		if len(s.testProperties.Data_device_libs) > 0 {
422			ctx.PropertyErrorf("data_device_libs", "only available for host modules")
423		}
424		if len(s.testProperties.Java_data) > 0 {
425			ctx.PropertyErrorf("Java_data", "only available for host modules")
426		}
427	}
428}
429
430func (s *ShTest) addToDataModules(ctx android.ModuleContext, relPath string, path android.Path) {
431	if _, exists := s.dataModules[relPath]; exists {
432		ctx.ModuleErrorf("data modules have a conflicting installation path, %v - %s, %s",
433			relPath, s.dataModules[relPath].String(), path.String())
434		return
435	}
436	s.dataModules[relPath] = path
437	s.data = append(s.data, android.DataPath{SrcPath: path})
438}
439
440func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
441	s.ShBinary.generateAndroidBuildActions(ctx)
442
443	expandedData := android.PathsForModuleSrc(ctx, s.testProperties.Data)
444	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_common_data)...)
445	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_first_data)...)
446	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Host_common_data)...)
447	// Emulate the data property for java_data dependencies.
448	for _, javaData := range ctx.GetDirectDepsProxyWithTag(shTestJavaDataTag) {
449		expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)
450	}
451	for _, d := range expandedData {
452		s.data = append(s.data, android.DataPath{SrcPath: d})
453	}
454
455	testDir := "nativetest"
456	if ctx.Target().Arch.ArchType.Multilib == "lib64" {
457		testDir = "nativetest64"
458	}
459	if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
460		testDir = filepath.Join(testDir, ctx.Target().NativeBridgeRelativePath)
461	} else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
462		testDir = filepath.Join(testDir, ctx.Arch().ArchType.String())
463	}
464	if s.SubDir() != "" {
465		// Don't add the module name to the installation path if sub_dir is specified for backward
466		// compatibility.
467		s.installDir = android.PathForModuleInstall(ctx, testDir, s.SubDir())
468	} else {
469		s.installDir = android.PathForModuleInstall(ctx, testDir, s.Name())
470	}
471
472	var configs []tradefed.Config
473	if Bool(s.testProperties.Require_root) {
474		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
475	} else {
476		options := []tradefed.Option{{Name: "force-root", Value: "false"}}
477		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
478	}
479	if len(s.testProperties.Data_device_bins) > 0 {
480		moduleName := s.Name()
481		remoteDir := "/data/local/tests/unrestricted/" + moduleName + "/"
482		options := []tradefed.Option{{Name: "cleanup", Value: "true"}}
483		for _, bin := range s.testProperties.Data_device_bins {
484			options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: remoteDir + bin})
485		}
486		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options})
487	}
488	s.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
489		TestConfigProp:         s.testProperties.Test_config,
490		TestConfigTemplateProp: s.testProperties.Test_config_template,
491		TestSuites:             s.testProperties.Test_suites,
492		Config:                 configs,
493		AutoGenConfig:          s.testProperties.Auto_gen_config,
494		OutputFileName:         s.outputFilePath.Base(),
495		DeviceTemplate:         "${ShellTestConfigTemplate}",
496		HostTemplate:           "${ShellTestConfigTemplate}",
497	})
498
499	s.extraTestConfigs = android.PathsForModuleSrc(ctx, s.testProperties.Extra_test_configs)
500	s.dataModules = make(map[string]android.Path)
501	ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
502		depTag := ctx.OtherModuleDependencyTag(dep)
503		switch depTag {
504		case shTestDataBinsTag, shTestDataDeviceBinsTag:
505			path := android.OutputFileForModule(ctx, dep, "")
506			s.addToDataModules(ctx, path.Base(), path)
507		case shTestDataLibsTag, shTestDataDeviceLibsTag:
508			if _, isCc := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider); isCc {
509				// Copy to an intermediate output directory to append "lib[64]" to the path,
510				// so that it's compatible with the default rpath values.
511				var relPath string
512				linkableInfo := android.OtherModuleProviderOrDefault(ctx, dep, cc.LinkableInfoProvider)
513				commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider)
514
515				if commonInfo.Target.Arch.ArchType.Multilib == "lib64" {
516					relPath = filepath.Join("lib64", linkableInfo.OutputFile.Path().Base())
517				} else {
518					relPath = filepath.Join("lib", linkableInfo.OutputFile.Path().Base())
519				}
520				if _, exist := s.dataModules[relPath]; exist {
521					return
522				}
523				relocatedLib := android.PathForModuleOut(ctx, "relocated").Join(ctx, relPath)
524				ctx.Build(pctx, android.BuildParams{
525					Rule:   android.Cp,
526					Input:  linkableInfo.OutputFile.Path(),
527					Output: relocatedLib,
528				})
529				s.addToDataModules(ctx, relPath, relocatedLib)
530				return
531			}
532			property := "data_libs"
533			if depTag == shTestDataDeviceBinsTag {
534				property = "data_device_libs"
535			}
536			ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
537		}
538	})
539
540	installedData := ctx.InstallTestData(s.installDir, s.data)
541	s.installedFile = ctx.InstallExecutable(s.installDir, s.outputFilePath.Base(), s.outputFilePath, installedData...)
542
543	mkEntries := s.AndroidMkEntries()[0]
544	android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
545		TestcaseRelDataFiles: addArch(ctx.Arch().ArchType.String(), installedData.Paths()),
546		OutputFile:           s.outputFilePath,
547		TestConfig:           s.testConfig,
548		TestSuites:           s.testProperties.Test_suites,
549		IsHost:               false,
550		IsUnitTest:           Bool(s.testProperties.Test_options.Unit_test),
551		MkInclude:            mkEntries.Include,
552		MkAppClass:           mkEntries.Class,
553		InstallDir:           s.installDir,
554	})
555
556	moduleInfoJSON := ctx.ModuleInfoJSON()
557	moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
558	if len(s.testProperties.Test_suites) > 0 {
559		moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, s.testProperties.Test_suites...)
560	} else {
561		moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
562	}
563	if proptools.Bool(s.testProperties.Test_options.Unit_test) {
564		moduleInfoJSON.IsUnitTest = "true"
565		if ctx.Host() {
566			moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
567		}
568	}
569	moduleInfoJSON.DataDependencies = append(moduleInfoJSON.DataDependencies, s.testProperties.Data_bins...)
570	if s.testConfig != nil {
571		if _, ok := s.testConfig.(android.WritablePath); ok {
572			moduleInfoJSON.AutoTestConfig = []string{"true"}
573		}
574		moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.testConfig.String())
575	}
576	moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.extraTestConfigs.Strings()...)
577
578	android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
579		TestSuites: s.testProperties.Test_suites,
580	})
581}
582
583func addArch(archType string, paths android.Paths) []string {
584	archRelPaths := []string{}
585	for _, p := range paths {
586		archRelPaths = append(archRelPaths, fmt.Sprintf("%s/%s", archType, p.Rel()))
587	}
588	return archRelPaths
589}
590
591func (s *ShTest) InstallInData() bool {
592	return true
593}
594
595func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries {
596	return []android.AndroidMkEntries{android.AndroidMkEntries{
597		Class:      "NATIVE_TESTS",
598		OutputFile: android.OptionalPathForPath(s.outputFilePath),
599		Include:    "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
600		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
601			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
602				s.customAndroidMkEntries(entries)
603				entries.SetPath("LOCAL_MODULE_PATH", s.installDir)
604				entries.AddCompatibilityTestSuites(s.testProperties.Test_suites...)
605				if s.testConfig != nil {
606					entries.SetPath("LOCAL_FULL_TEST_CONFIG", s.testConfig)
607				}
608				if s.testProperties.Data_bins != nil {
609					entries.AddStrings("LOCAL_TEST_DATA_BINS", s.testProperties.Data_bins...)
610				}
611				entries.SetBoolIfTrue("LOCAL_COMPATIBILITY_PER_TESTCASE_DIRECTORY", Bool(s.testProperties.Per_testcase_directory))
612				if len(s.extraTestConfigs) > 0 {
613					entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", s.extraTestConfigs.Strings()...)
614				}
615
616				entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !proptools.BoolDefault(s.testProperties.Auto_gen_config, true))
617
618				s.testProperties.Test_options.SetAndroidMkEntries(entries)
619			},
620		},
621	}}
622}
623
624func initShBinaryModule(s *ShBinary) {
625	s.AddProperties(&s.properties)
626}
627
628// sh_binary is for a shell script or batch file to be installed as an
629// executable binary to <partition>/bin.
630func ShBinaryFactory() android.Module {
631	module := &ShBinary{}
632	initShBinaryModule(module)
633	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
634	android.InitDefaultableModule(module)
635	return module
636}
637
638// sh_binary_host is for a shell script to be installed as an executable binary
639// to $(HOST_OUT)/bin.
640func ShBinaryHostFactory() android.Module {
641	module := &ShBinary{}
642	initShBinaryModule(module)
643	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
644	android.InitDefaultableModule(module)
645	return module
646}
647
648// sh_test defines a shell script based test module.
649func ShTestFactory() android.Module {
650	module := &ShTest{}
651	initShBinaryModule(&module.ShBinary)
652	module.AddProperties(&module.testProperties)
653
654	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
655	android.InitDefaultableModule(module)
656	return module
657}
658
659// sh_test_host defines a shell script based test module that runs on a host.
660func ShTestHostFactory() android.Module {
661	module := &ShTest{}
662	initShBinaryModule(&module.ShBinary)
663	module.AddProperties(&module.testProperties)
664	// Default sh_test_host to unit_tests = true
665	if module.testProperties.Test_options.Unit_test == nil {
666		module.testProperties.Test_options.Unit_test = proptools.BoolPtr(true)
667	}
668
669	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
670	android.InitDefaultableModule(module)
671	return module
672}
673
674type ShDefaults struct {
675	android.ModuleBase
676	android.DefaultsModuleBase
677}
678
679func ShDefaultsFactory() android.Module {
680	module := &ShDefaults{}
681
682	module.AddProperties(&shBinaryProperties{}, &TestProperties{})
683	android.InitDefaultsModule(module)
684
685	return module
686}
687
688var Bool = proptools.Bool
689