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