xref: /aosp_15_r20/build/soong/genrule/genrule.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2015 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Worker// A genrule module takes a list of source files ("srcs" property), an optional
16*333d2b36SAndroid Build Coastguard Worker// list of tools ("tools" property), and a command line ("cmd" property), to
17*333d2b36SAndroid Build Coastguard Worker// generate output files ("out" property).
18*333d2b36SAndroid Build Coastguard Worker
19*333d2b36SAndroid Build Coastguard Workerpackage genrule
20*333d2b36SAndroid Build Coastguard Worker
21*333d2b36SAndroid Build Coastguard Workerimport (
22*333d2b36SAndroid Build Coastguard Worker	"fmt"
23*333d2b36SAndroid Build Coastguard Worker	"io"
24*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
25*333d2b36SAndroid Build Coastguard Worker	"strconv"
26*333d2b36SAndroid Build Coastguard Worker	"strings"
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
29*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
30*333d2b36SAndroid Build Coastguard Worker
31*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
32*333d2b36SAndroid Build Coastguard Worker)
33*333d2b36SAndroid Build Coastguard Worker
34*333d2b36SAndroid Build Coastguard Workerfunc init() {
35*333d2b36SAndroid Build Coastguard Worker	RegisterGenruleBuildComponents(android.InitRegistrationContext)
36*333d2b36SAndroid Build Coastguard Worker}
37*333d2b36SAndroid Build Coastguard Worker
38*333d2b36SAndroid Build Coastguard Worker// Test fixture preparer that will register most genrule build components.
39*333d2b36SAndroid Build Coastguard Worker//
40*333d2b36SAndroid Build Coastguard Worker// Singletons and mutators should only be added here if they are needed for a majority of genrule
41*333d2b36SAndroid Build Coastguard Worker// module types, otherwise they should be added under a separate preparer to allow them to be
42*333d2b36SAndroid Build Coastguard Worker// selected only when needed to reduce test execution time.
43*333d2b36SAndroid Build Coastguard Worker//
44*333d2b36SAndroid Build Coastguard Worker// Module types do not have much of an overhead unless they are used so this should include as many
45*333d2b36SAndroid Build Coastguard Worker// module types as possible. The exceptions are those module types that require mutators and/or
46*333d2b36SAndroid Build Coastguard Worker// singletons in order to function in which case they should be kept together in a separate
47*333d2b36SAndroid Build Coastguard Worker// preparer.
48*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithGenRuleBuildComponents = android.GroupFixturePreparers(
49*333d2b36SAndroid Build Coastguard Worker	android.FixtureRegisterWithContext(RegisterGenruleBuildComponents),
50*333d2b36SAndroid Build Coastguard Worker)
51*333d2b36SAndroid Build Coastguard Worker
52*333d2b36SAndroid Build Coastguard Worker// Prepare a fixture to use all genrule module types, mutators and singletons fully.
53*333d2b36SAndroid Build Coastguard Worker//
54*333d2b36SAndroid Build Coastguard Worker// This should only be used by tests that want to run with as much of the build enabled as possible.
55*333d2b36SAndroid Build Coastguard Workervar PrepareForIntegrationTestWithGenrule = android.GroupFixturePreparers(
56*333d2b36SAndroid Build Coastguard Worker	PrepareForTestWithGenRuleBuildComponents,
57*333d2b36SAndroid Build Coastguard Worker)
58*333d2b36SAndroid Build Coastguard Worker
59*333d2b36SAndroid Build Coastguard Workerfunc RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
60*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
61*333d2b36SAndroid Build Coastguard Worker
62*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterModuleType("gensrcs", GenSrcsFactory)
63*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterModuleType("genrule", GenRuleFactory)
64*333d2b36SAndroid Build Coastguard Worker
65*333d2b36SAndroid Build Coastguard Worker	ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
66*333d2b36SAndroid Build Coastguard Worker		ctx.BottomUp("genrule_tool_deps", toolDepsMutator)
67*333d2b36SAndroid Build Coastguard Worker	})
68*333d2b36SAndroid Build Coastguard Worker}
69*333d2b36SAndroid Build Coastguard Worker
70*333d2b36SAndroid Build Coastguard Workervar (
71*333d2b36SAndroid Build Coastguard Worker	pctx = android.NewPackageContext("android/soong/genrule")
72*333d2b36SAndroid Build Coastguard Worker
73*333d2b36SAndroid Build Coastguard Worker	// Used by gensrcs when there is more than 1 shard to merge the outputs
74*333d2b36SAndroid Build Coastguard Worker	// of each shard into a zip file.
75*333d2b36SAndroid Build Coastguard Worker	gensrcsMerge = pctx.AndroidStaticRule("gensrcsMerge", blueprint.RuleParams{
76*333d2b36SAndroid Build Coastguard Worker		Command:        "${soongZip} -o ${tmpZip} @${tmpZip}.rsp && ${zipSync} -d ${genDir} ${tmpZip}",
77*333d2b36SAndroid Build Coastguard Worker		CommandDeps:    []string{"${soongZip}", "${zipSync}"},
78*333d2b36SAndroid Build Coastguard Worker		Rspfile:        "${tmpZip}.rsp",
79*333d2b36SAndroid Build Coastguard Worker		RspfileContent: "${zipArgs}",
80*333d2b36SAndroid Build Coastguard Worker	}, "tmpZip", "genDir", "zipArgs")
81*333d2b36SAndroid Build Coastguard Worker)
82*333d2b36SAndroid Build Coastguard Worker
83*333d2b36SAndroid Build Coastguard Workerfunc init() {
84*333d2b36SAndroid Build Coastguard Worker	pctx.Import("android/soong/android")
85*333d2b36SAndroid Build Coastguard Worker
86*333d2b36SAndroid Build Coastguard Worker	pctx.HostBinToolVariable("soongZip", "soong_zip")
87*333d2b36SAndroid Build Coastguard Worker	pctx.HostBinToolVariable("zipSync", "zipsync")
88*333d2b36SAndroid Build Coastguard Worker}
89*333d2b36SAndroid Build Coastguard Worker
90*333d2b36SAndroid Build Coastguard Workertype SourceFileGenerator interface {
91*333d2b36SAndroid Build Coastguard Worker	GeneratedSourceFiles() android.Paths
92*333d2b36SAndroid Build Coastguard Worker	GeneratedHeaderDirs() android.Paths
93*333d2b36SAndroid Build Coastguard Worker	GeneratedDeps() android.Paths
94*333d2b36SAndroid Build Coastguard Worker}
95*333d2b36SAndroid Build Coastguard Worker
96*333d2b36SAndroid Build Coastguard Worker// Alias for android.HostToolProvider
97*333d2b36SAndroid Build Coastguard Worker// Deprecated: use android.HostToolProvider instead.
98*333d2b36SAndroid Build Coastguard Workertype HostToolProvider interface {
99*333d2b36SAndroid Build Coastguard Worker	android.HostToolProvider
100*333d2b36SAndroid Build Coastguard Worker}
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Workertype hostToolDependencyTag struct {
103*333d2b36SAndroid Build Coastguard Worker	blueprint.BaseDependencyTag
104*333d2b36SAndroid Build Coastguard Worker	android.LicenseAnnotationToolchainDependencyTag
105*333d2b36SAndroid Build Coastguard Worker	label string
106*333d2b36SAndroid Build Coastguard Worker}
107*333d2b36SAndroid Build Coastguard Worker
108*333d2b36SAndroid Build Coastguard Workerfunc (t hostToolDependencyTag) AllowDisabledModuleDependency(target android.Module) bool {
109*333d2b36SAndroid Build Coastguard Worker	// Allow depending on a disabled module if it's replaced by a prebuilt
110*333d2b36SAndroid Build Coastguard Worker	// counterpart. We get the prebuilt through android.PrebuiltGetPreferred in
111*333d2b36SAndroid Build Coastguard Worker	// GenerateAndroidBuildActions.
112*333d2b36SAndroid Build Coastguard Worker	return target.IsReplacedByPrebuilt()
113*333d2b36SAndroid Build Coastguard Worker}
114*333d2b36SAndroid Build Coastguard Worker
115*333d2b36SAndroid Build Coastguard Workerfunc (t hostToolDependencyTag) AllowDisabledModuleDependencyProxy(
116*333d2b36SAndroid Build Coastguard Worker	ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
117*333d2b36SAndroid Build Coastguard Worker	return android.OtherModuleProviderOrDefault(
118*333d2b36SAndroid Build Coastguard Worker		ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt
119*333d2b36SAndroid Build Coastguard Worker}
120*333d2b36SAndroid Build Coastguard Worker
121*333d2b36SAndroid Build Coastguard Workervar _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil)
122*333d2b36SAndroid Build Coastguard Worker
123*333d2b36SAndroid Build Coastguard Workertype generatorProperties struct {
124*333d2b36SAndroid Build Coastguard Worker	// The command to run on one or more input files. Cmd supports substitution of a few variables.
125*333d2b36SAndroid Build Coastguard Worker	//
126*333d2b36SAndroid Build Coastguard Worker	// Available variables for substitution:
127*333d2b36SAndroid Build Coastguard Worker	//
128*333d2b36SAndroid Build Coastguard Worker	//  $(location): the path to the first entry in tools or tool_files.
129*333d2b36SAndroid Build Coastguard Worker	//  $(location <label>): the path to the tool, tool_file, input or output with name <label>. Use $(location) if <label> refers to a rule that outputs exactly one file.
130*333d2b36SAndroid Build Coastguard Worker	//  $(locations <label>): the paths to the tools, tool_files, inputs or outputs with name <label>. Use $(locations) if <label> refers to a rule that outputs two or more files.
131*333d2b36SAndroid Build Coastguard Worker	//  $(in): one or more input files.
132*333d2b36SAndroid Build Coastguard Worker	//  $(out): a single output file.
133*333d2b36SAndroid Build Coastguard Worker	//  $(genDir): the sandbox directory for this tool; contains $(out).
134*333d2b36SAndroid Build Coastguard Worker	//  $$: a literal $
135*333d2b36SAndroid Build Coastguard Worker	Cmd proptools.Configurable[string] `android:"replace_instead_of_append"`
136*333d2b36SAndroid Build Coastguard Worker
137*333d2b36SAndroid Build Coastguard Worker	// name of the modules (if any) that produces the host executable.   Leave empty for
138*333d2b36SAndroid Build Coastguard Worker	// prebuilts or scripts that do not need a module to build them.
139*333d2b36SAndroid Build Coastguard Worker	Tools []string
140*333d2b36SAndroid Build Coastguard Worker
141*333d2b36SAndroid Build Coastguard Worker	// Local files that are used by the tool
142*333d2b36SAndroid Build Coastguard Worker	Tool_files []string `android:"path"`
143*333d2b36SAndroid Build Coastguard Worker
144*333d2b36SAndroid Build Coastguard Worker	// List of directories to export generated headers from
145*333d2b36SAndroid Build Coastguard Worker	Export_include_dirs []string
146*333d2b36SAndroid Build Coastguard Worker
147*333d2b36SAndroid Build Coastguard Worker	// list of input files
148*333d2b36SAndroid Build Coastguard Worker	Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
149*333d2b36SAndroid Build Coastguard Worker
150*333d2b36SAndroid Build Coastguard Worker	// Same as srcs, but will add dependencies on modules via a device os variation and the device's
151*333d2b36SAndroid Build Coastguard Worker	// first supported arch's variation. Can be used to add a dependency from a host genrule to
152*333d2b36SAndroid Build Coastguard Worker	// a device module.
153*333d2b36SAndroid Build Coastguard Worker	Device_first_srcs proptools.Configurable[[]string] `android:"path_device_first"`
154*333d2b36SAndroid Build Coastguard Worker
155*333d2b36SAndroid Build Coastguard Worker	// Same as srcs, but will add dependencies on modules via a device os variation and the common
156*333d2b36SAndroid Build Coastguard Worker	// arch variation. Can be used to add a dependency from a host genrule to a device module.
157*333d2b36SAndroid Build Coastguard Worker	Device_common_srcs proptools.Configurable[[]string] `android:"path_device_common"`
158*333d2b36SAndroid Build Coastguard Worker
159*333d2b36SAndroid Build Coastguard Worker	// Same as srcs, but will add dependencies on modules via a common_os os variation.
160*333d2b36SAndroid Build Coastguard Worker	Common_os_srcs proptools.Configurable[[]string] `android:"path_common_os"`
161*333d2b36SAndroid Build Coastguard Worker
162*333d2b36SAndroid Build Coastguard Worker	// input files to exclude
163*333d2b36SAndroid Build Coastguard Worker	Exclude_srcs []string `android:"path,arch_variant"`
164*333d2b36SAndroid Build Coastguard Worker
165*333d2b36SAndroid Build Coastguard Worker	// Enable restat to update the output only if the output is changed
166*333d2b36SAndroid Build Coastguard Worker	Write_if_changed *bool
167*333d2b36SAndroid Build Coastguard Worker
168*333d2b36SAndroid Build Coastguard Worker	// When set to true, an additional $(build_number_file) label will be available
169*333d2b36SAndroid Build Coastguard Worker	// to use in the cmd. This will be the location of a text file containing the
170*333d2b36SAndroid Build Coastguard Worker	// build number. The dependency on this file will be "order-only", meaning that
171*333d2b36SAndroid Build Coastguard Worker	// the genrule will not rerun when only this file changes, to avoid rerunning
172*333d2b36SAndroid Build Coastguard Worker	// the genrule every build, because the build number changes every build.
173*333d2b36SAndroid Build Coastguard Worker	// This also means that you should not attempt to consume the build number from
174*333d2b36SAndroid Build Coastguard Worker	// the result of this genrule in another build rule. If you do, the build number
175*333d2b36SAndroid Build Coastguard Worker	// in the second build rule will be stale when the second build rule rebuilds
176*333d2b36SAndroid Build Coastguard Worker	// but this genrule does not. Only certain allowlisted modules are allowed to
177*333d2b36SAndroid Build Coastguard Worker	// use this property, usages of the build number should be kept to the absolute
178*333d2b36SAndroid Build Coastguard Worker	// minimum. Particularly no modules on the system image may include the build
179*333d2b36SAndroid Build Coastguard Worker	// number. Prefer using libbuildversion via the use_version_lib property on
180*333d2b36SAndroid Build Coastguard Worker	// cc modules.
181*333d2b36SAndroid Build Coastguard Worker	Uses_order_only_build_number_file *bool
182*333d2b36SAndroid Build Coastguard Worker}
183*333d2b36SAndroid Build Coastguard Worker
184*333d2b36SAndroid Build Coastguard Workertype Module struct {
185*333d2b36SAndroid Build Coastguard Worker	android.ModuleBase
186*333d2b36SAndroid Build Coastguard Worker	android.DefaultableModuleBase
187*333d2b36SAndroid Build Coastguard Worker	android.ApexModuleBase
188*333d2b36SAndroid Build Coastguard Worker
189*333d2b36SAndroid Build Coastguard Worker	// For other packages to make their own genrules with extra
190*333d2b36SAndroid Build Coastguard Worker	// properties
191*333d2b36SAndroid Build Coastguard Worker	Extra interface{}
192*333d2b36SAndroid Build Coastguard Worker
193*333d2b36SAndroid Build Coastguard Worker	// CmdModifier can be set by wrappers around genrule to modify the command, for example to
194*333d2b36SAndroid Build Coastguard Worker	// prefix environment variables to it.
195*333d2b36SAndroid Build Coastguard Worker	CmdModifier func(ctx android.ModuleContext, cmd string) string
196*333d2b36SAndroid Build Coastguard Worker
197*333d2b36SAndroid Build Coastguard Worker	android.ImageInterface
198*333d2b36SAndroid Build Coastguard Worker
199*333d2b36SAndroid Build Coastguard Worker	properties generatorProperties
200*333d2b36SAndroid Build Coastguard Worker
201*333d2b36SAndroid Build Coastguard Worker	// For the different tasks that genrule and gensrc generate. genrule will
202*333d2b36SAndroid Build Coastguard Worker	// generate 1 task, and gensrc will generate 1 or more tasks based on the
203*333d2b36SAndroid Build Coastguard Worker	// number of shards the input files are sharded into.
204*333d2b36SAndroid Build Coastguard Worker	taskGenerator taskFunc
205*333d2b36SAndroid Build Coastguard Worker
206*333d2b36SAndroid Build Coastguard Worker	rule        blueprint.Rule
207*333d2b36SAndroid Build Coastguard Worker	rawCommands []string
208*333d2b36SAndroid Build Coastguard Worker
209*333d2b36SAndroid Build Coastguard Worker	exportedIncludeDirs android.Paths
210*333d2b36SAndroid Build Coastguard Worker
211*333d2b36SAndroid Build Coastguard Worker	outputFiles android.Paths
212*333d2b36SAndroid Build Coastguard Worker	outputDeps  android.Paths
213*333d2b36SAndroid Build Coastguard Worker
214*333d2b36SAndroid Build Coastguard Worker	subName string
215*333d2b36SAndroid Build Coastguard Worker	subDir  string
216*333d2b36SAndroid Build Coastguard Worker}
217*333d2b36SAndroid Build Coastguard Worker
218*333d2b36SAndroid Build Coastguard Workertype taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask
219*333d2b36SAndroid Build Coastguard Worker
220*333d2b36SAndroid Build Coastguard Workertype generateTask struct {
221*333d2b36SAndroid Build Coastguard Worker	in          android.Paths
222*333d2b36SAndroid Build Coastguard Worker	out         android.WritablePaths
223*333d2b36SAndroid Build Coastguard Worker	copyTo      android.WritablePaths // For gensrcs to set on gensrcsMerge rule.
224*333d2b36SAndroid Build Coastguard Worker	genDir      android.WritablePath
225*333d2b36SAndroid Build Coastguard Worker	extraInputs map[string][]string
226*333d2b36SAndroid Build Coastguard Worker
227*333d2b36SAndroid Build Coastguard Worker	cmd string
228*333d2b36SAndroid Build Coastguard Worker	// For gensrsc sharding.
229*333d2b36SAndroid Build Coastguard Worker	shard  int
230*333d2b36SAndroid Build Coastguard Worker	shards int
231*333d2b36SAndroid Build Coastguard Worker
232*333d2b36SAndroid Build Coastguard Worker	// For nsjail tasks
233*333d2b36SAndroid Build Coastguard Worker	useNsjail  bool
234*333d2b36SAndroid Build Coastguard Worker	dirSrcs    android.DirectoryPaths
235*333d2b36SAndroid Build Coastguard Worker	keepGendir bool
236*333d2b36SAndroid Build Coastguard Worker}
237*333d2b36SAndroid Build Coastguard Worker
238*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) GeneratedSourceFiles() android.Paths {
239*333d2b36SAndroid Build Coastguard Worker	return g.outputFiles
240*333d2b36SAndroid Build Coastguard Worker}
241*333d2b36SAndroid Build Coastguard Worker
242*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) Srcs() android.Paths {
243*333d2b36SAndroid Build Coastguard Worker	return append(android.Paths{}, g.outputFiles...)
244*333d2b36SAndroid Build Coastguard Worker}
245*333d2b36SAndroid Build Coastguard Worker
246*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) GeneratedHeaderDirs() android.Paths {
247*333d2b36SAndroid Build Coastguard Worker	return g.exportedIncludeDirs
248*333d2b36SAndroid Build Coastguard Worker}
249*333d2b36SAndroid Build Coastguard Worker
250*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) GeneratedDeps() android.Paths {
251*333d2b36SAndroid Build Coastguard Worker	return g.outputDeps
252*333d2b36SAndroid Build Coastguard Worker}
253*333d2b36SAndroid Build Coastguard Worker
254*333d2b36SAndroid Build Coastguard Workervar _ android.SourceFileProducer = (*Module)(nil)
255*333d2b36SAndroid Build Coastguard Worker
256*333d2b36SAndroid Build Coastguard Workerfunc toolDepsMutator(ctx android.BottomUpMutatorContext) {
257*333d2b36SAndroid Build Coastguard Worker	if g, ok := ctx.Module().(*Module); ok {
258*333d2b36SAndroid Build Coastguard Worker		for _, tool := range g.properties.Tools {
259*333d2b36SAndroid Build Coastguard Worker			tag := hostToolDependencyTag{label: tool}
260*333d2b36SAndroid Build Coastguard Worker			if m := android.SrcIsModule(tool); m != "" {
261*333d2b36SAndroid Build Coastguard Worker				tool = m
262*333d2b36SAndroid Build Coastguard Worker			}
263*333d2b36SAndroid Build Coastguard Worker			ctx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), tag, tool)
264*333d2b36SAndroid Build Coastguard Worker		}
265*333d2b36SAndroid Build Coastguard Worker	}
266*333d2b36SAndroid Build Coastguard Worker}
267*333d2b36SAndroid Build Coastguard Worker
268*333d2b36SAndroid Build Coastguard Workervar buildNumberAllowlistKey = android.NewOnceKey("genruleBuildNumberAllowlistKey")
269*333d2b36SAndroid Build Coastguard Worker
270*333d2b36SAndroid Build Coastguard Worker// This allowlist should be kept to the bare minimum, it's
271*333d2b36SAndroid Build Coastguard Worker// intended for things that existed before the build number
272*333d2b36SAndroid Build Coastguard Worker// was tightly controlled. Prefer using libbuildversion
273*333d2b36SAndroid Build Coastguard Worker// via the use_version_lib property of cc modules.
274*333d2b36SAndroid Build Coastguard Worker// This is a function instead of a global map so that
275*333d2b36SAndroid Build Coastguard Worker// soong plugins cannot add entries to the allowlist
276*333d2b36SAndroid Build Coastguard Workerfunc isModuleInBuildNumberAllowlist(ctx android.ModuleContext) bool {
277*333d2b36SAndroid Build Coastguard Worker	allowlist := ctx.Config().Once(buildNumberAllowlistKey, func() interface{} {
278*333d2b36SAndroid Build Coastguard Worker		// Define the allowlist as a list and then copy it into a map so that
279*333d2b36SAndroid Build Coastguard Worker		// gofmt doesn't change unnecessary lines trying to align the values of the map.
280*333d2b36SAndroid Build Coastguard Worker		allowlist := []string{
281*333d2b36SAndroid Build Coastguard Worker			// go/keep-sorted start
282*333d2b36SAndroid Build Coastguard Worker			"build/soong/tests:gen",
283*333d2b36SAndroid Build Coastguard Worker			"hardware/google/camera/common/hal/aidl_service:aidl_camera_build_version",
284*333d2b36SAndroid Build Coastguard Worker			"tools/tradefederation/core:tradefed_zip",
285*333d2b36SAndroid Build Coastguard Worker			"vendor/google/services/LyricCameraHAL/src/apex:com.google.pixel.camera.hal.manifest",
286*333d2b36SAndroid Build Coastguard Worker			// go/keep-sorted end
287*333d2b36SAndroid Build Coastguard Worker		}
288*333d2b36SAndroid Build Coastguard Worker		allowlistMap := make(map[string]bool, len(allowlist))
289*333d2b36SAndroid Build Coastguard Worker		for _, a := range allowlist {
290*333d2b36SAndroid Build Coastguard Worker			allowlistMap[a] = true
291*333d2b36SAndroid Build Coastguard Worker		}
292*333d2b36SAndroid Build Coastguard Worker		return allowlistMap
293*333d2b36SAndroid Build Coastguard Worker	}).(map[string]bool)
294*333d2b36SAndroid Build Coastguard Worker
295*333d2b36SAndroid Build Coastguard Worker	_, ok := allowlist[ctx.ModuleDir()+":"+ctx.ModuleName()]
296*333d2b36SAndroid Build Coastguard Worker	return ok
297*333d2b36SAndroid Build Coastguard Worker}
298*333d2b36SAndroid Build Coastguard Worker
299*333d2b36SAndroid Build Coastguard Worker// generateCommonBuildActions contains build action generation logic
300*333d2b36SAndroid Build Coastguard Worker// common to both the mixed build case and the legacy case of genrule processing.
301*333d2b36SAndroid Build Coastguard Worker// To fully support genrule in mixed builds, the contents of this function should
302*333d2b36SAndroid Build Coastguard Worker// approach zero; there should be no genrule action registration done directly
303*333d2b36SAndroid Build Coastguard Worker// by Soong logic in the mixed-build case.
304*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
305*333d2b36SAndroid Build Coastguard Worker	// Add the variant as a suffix to the make modules to create, so that the make modules
306*333d2b36SAndroid Build Coastguard Worker	// don't conflict because make doesn't know about variants. However, this causes issues with
307*333d2b36SAndroid Build Coastguard Worker	// tracking required dependencies as the required property in soong is passed straight to make
308*333d2b36SAndroid Build Coastguard Worker	// without accounting for these suffixes. To make it a little easier to work with, don't use
309*333d2b36SAndroid Build Coastguard Worker	// a suffix for android_common variants so that java_genrules look like regular 1-variant
310*333d2b36SAndroid Build Coastguard Worker	// genrules to make.
311*333d2b36SAndroid Build Coastguard Worker	if ctx.ModuleSubDir() != "android_common" {
312*333d2b36SAndroid Build Coastguard Worker		g.subName = ctx.ModuleSubDir()
313*333d2b36SAndroid Build Coastguard Worker	}
314*333d2b36SAndroid Build Coastguard Worker
315*333d2b36SAndroid Build Coastguard Worker	if len(g.properties.Export_include_dirs) > 0 {
316*333d2b36SAndroid Build Coastguard Worker		for _, dir := range g.properties.Export_include_dirs {
317*333d2b36SAndroid Build Coastguard Worker			g.exportedIncludeDirs = append(g.exportedIncludeDirs,
318*333d2b36SAndroid Build Coastguard Worker				android.PathForModuleGen(ctx, g.subDir, ctx.ModuleDir(), dir))
319*333d2b36SAndroid Build Coastguard Worker			// Also export without ModuleDir for consistency with Export_include_dirs not being set
320*333d2b36SAndroid Build Coastguard Worker			g.exportedIncludeDirs = append(g.exportedIncludeDirs,
321*333d2b36SAndroid Build Coastguard Worker				android.PathForModuleGen(ctx, g.subDir, dir))
322*333d2b36SAndroid Build Coastguard Worker		}
323*333d2b36SAndroid Build Coastguard Worker	} else {
324*333d2b36SAndroid Build Coastguard Worker		g.exportedIncludeDirs = append(g.exportedIncludeDirs, android.PathForModuleGen(ctx, g.subDir))
325*333d2b36SAndroid Build Coastguard Worker	}
326*333d2b36SAndroid Build Coastguard Worker
327*333d2b36SAndroid Build Coastguard Worker	locationLabels := map[string]location{}
328*333d2b36SAndroid Build Coastguard Worker	firstLabel := ""
329*333d2b36SAndroid Build Coastguard Worker
330*333d2b36SAndroid Build Coastguard Worker	addLocationLabel := func(label string, loc location) {
331*333d2b36SAndroid Build Coastguard Worker		if firstLabel == "" {
332*333d2b36SAndroid Build Coastguard Worker			firstLabel = label
333*333d2b36SAndroid Build Coastguard Worker		}
334*333d2b36SAndroid Build Coastguard Worker		if _, exists := locationLabels[label]; !exists {
335*333d2b36SAndroid Build Coastguard Worker			locationLabels[label] = loc
336*333d2b36SAndroid Build Coastguard Worker		} else {
337*333d2b36SAndroid Build Coastguard Worker			ctx.ModuleErrorf("multiple locations for label %q: %q and %q (do you have duplicate srcs entries?)",
338*333d2b36SAndroid Build Coastguard Worker				label, locationLabels[label], loc)
339*333d2b36SAndroid Build Coastguard Worker		}
340*333d2b36SAndroid Build Coastguard Worker	}
341*333d2b36SAndroid Build Coastguard Worker
342*333d2b36SAndroid Build Coastguard Worker	var tools android.Paths
343*333d2b36SAndroid Build Coastguard Worker	var packagedTools []android.PackagingSpec
344*333d2b36SAndroid Build Coastguard Worker	if len(g.properties.Tools) > 0 {
345*333d2b36SAndroid Build Coastguard Worker		seenTools := make(map[string]bool)
346*333d2b36SAndroid Build Coastguard Worker		ctx.VisitDirectDepsProxyAllowDisabled(func(proxy android.ModuleProxy) {
347*333d2b36SAndroid Build Coastguard Worker			switch tag := ctx.OtherModuleDependencyTag(proxy).(type) {
348*333d2b36SAndroid Build Coastguard Worker			case hostToolDependencyTag:
349*333d2b36SAndroid Build Coastguard Worker				// Necessary to retrieve any prebuilt replacement for the tool, since
350*333d2b36SAndroid Build Coastguard Worker				// toolDepsMutator runs too late for the prebuilt mutators to have
351*333d2b36SAndroid Build Coastguard Worker				// replaced the dependency.
352*333d2b36SAndroid Build Coastguard Worker				module := android.PrebuiltGetPreferred(ctx, proxy)
353*333d2b36SAndroid Build Coastguard Worker				tool := ctx.OtherModuleName(module)
354*333d2b36SAndroid Build Coastguard Worker				if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderKey); ok {
355*333d2b36SAndroid Build Coastguard Worker					// A HostToolProvider provides the path to a tool, which will be copied
356*333d2b36SAndroid Build Coastguard Worker					// into the sandbox.
357*333d2b36SAndroid Build Coastguard Worker					if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled {
358*333d2b36SAndroid Build Coastguard Worker						if ctx.Config().AllowMissingDependencies() {
359*333d2b36SAndroid Build Coastguard Worker							ctx.AddMissingDependencies([]string{tool})
360*333d2b36SAndroid Build Coastguard Worker						} else {
361*333d2b36SAndroid Build Coastguard Worker							ctx.ModuleErrorf("depends on disabled module %q", tool)
362*333d2b36SAndroid Build Coastguard Worker						}
363*333d2b36SAndroid Build Coastguard Worker						return
364*333d2b36SAndroid Build Coastguard Worker					}
365*333d2b36SAndroid Build Coastguard Worker					path := h.HostToolPath
366*333d2b36SAndroid Build Coastguard Worker					if !path.Valid() {
367*333d2b36SAndroid Build Coastguard Worker						ctx.ModuleErrorf("host tool %q missing output file", tool)
368*333d2b36SAndroid Build Coastguard Worker						return
369*333d2b36SAndroid Build Coastguard Worker					}
370*333d2b36SAndroid Build Coastguard Worker					if specs := android.OtherModuleProviderOrDefault(
371*333d2b36SAndroid Build Coastguard Worker						ctx, module, android.InstallFilesProvider).TransitivePackagingSpecs.ToList(); specs != nil {
372*333d2b36SAndroid Build Coastguard Worker						// If the HostToolProvider has PackgingSpecs, which are definitions of the
373*333d2b36SAndroid Build Coastguard Worker						// required relative locations of the tool and its dependencies, use those
374*333d2b36SAndroid Build Coastguard Worker						// instead.  They will be copied to those relative locations in the sbox
375*333d2b36SAndroid Build Coastguard Worker						// sandbox.
376*333d2b36SAndroid Build Coastguard Worker						// Care must be taken since TransitivePackagingSpec may return device-side
377*333d2b36SAndroid Build Coastguard Worker						// paths via the required property. Filter them out.
378*333d2b36SAndroid Build Coastguard Worker						for i, ps := range specs {
379*333d2b36SAndroid Build Coastguard Worker							if ps.Partition() != "" {
380*333d2b36SAndroid Build Coastguard Worker								if i == 0 {
381*333d2b36SAndroid Build Coastguard Worker									panic("first PackagingSpec is assumed to be the host-side tool")
382*333d2b36SAndroid Build Coastguard Worker								}
383*333d2b36SAndroid Build Coastguard Worker								continue
384*333d2b36SAndroid Build Coastguard Worker							}
385*333d2b36SAndroid Build Coastguard Worker							packagedTools = append(packagedTools, ps)
386*333d2b36SAndroid Build Coastguard Worker						}
387*333d2b36SAndroid Build Coastguard Worker						// Assume that the first PackagingSpec of the module is the tool.
388*333d2b36SAndroid Build Coastguard Worker						addLocationLabel(tag.label, packagedToolLocation{specs[0]})
389*333d2b36SAndroid Build Coastguard Worker					} else {
390*333d2b36SAndroid Build Coastguard Worker						tools = append(tools, path.Path())
391*333d2b36SAndroid Build Coastguard Worker						addLocationLabel(tag.label, toolLocation{android.Paths{path.Path()}})
392*333d2b36SAndroid Build Coastguard Worker					}
393*333d2b36SAndroid Build Coastguard Worker				} else {
394*333d2b36SAndroid Build Coastguard Worker					ctx.ModuleErrorf("%q is not a host tool provider", tool)
395*333d2b36SAndroid Build Coastguard Worker					return
396*333d2b36SAndroid Build Coastguard Worker				}
397*333d2b36SAndroid Build Coastguard Worker
398*333d2b36SAndroid Build Coastguard Worker				seenTools[tag.label] = true
399*333d2b36SAndroid Build Coastguard Worker			}
400*333d2b36SAndroid Build Coastguard Worker		})
401*333d2b36SAndroid Build Coastguard Worker
402*333d2b36SAndroid Build Coastguard Worker		// If AllowMissingDependencies is enabled, the build will not have stopped when
403*333d2b36SAndroid Build Coastguard Worker		// AddFarVariationDependencies was called on a missing tool, which will result in nonsensical
404*333d2b36SAndroid Build Coastguard Worker		// "cmd: unknown location label ..." errors later.  Add a placeholder file to the local label.
405*333d2b36SAndroid Build Coastguard Worker		// The command that uses this placeholder file will never be executed because the rule will be
406*333d2b36SAndroid Build Coastguard Worker		// replaced with an android.Error rule reporting the missing dependencies.
407*333d2b36SAndroid Build Coastguard Worker		if ctx.Config().AllowMissingDependencies() {
408*333d2b36SAndroid Build Coastguard Worker			for _, tool := range g.properties.Tools {
409*333d2b36SAndroid Build Coastguard Worker				if !seenTools[tool] {
410*333d2b36SAndroid Build Coastguard Worker					addLocationLabel(tool, errorLocation{"***missing tool " + tool + "***"})
411*333d2b36SAndroid Build Coastguard Worker				}
412*333d2b36SAndroid Build Coastguard Worker			}
413*333d2b36SAndroid Build Coastguard Worker		}
414*333d2b36SAndroid Build Coastguard Worker	}
415*333d2b36SAndroid Build Coastguard Worker
416*333d2b36SAndroid Build Coastguard Worker	if ctx.Failed() {
417*333d2b36SAndroid Build Coastguard Worker		return
418*333d2b36SAndroid Build Coastguard Worker	}
419*333d2b36SAndroid Build Coastguard Worker
420*333d2b36SAndroid Build Coastguard Worker	for _, toolFile := range g.properties.Tool_files {
421*333d2b36SAndroid Build Coastguard Worker		paths := android.PathsForModuleSrc(ctx, []string{toolFile})
422*333d2b36SAndroid Build Coastguard Worker		tools = append(tools, paths...)
423*333d2b36SAndroid Build Coastguard Worker		addLocationLabel(toolFile, toolLocation{paths})
424*333d2b36SAndroid Build Coastguard Worker	}
425*333d2b36SAndroid Build Coastguard Worker
426*333d2b36SAndroid Build Coastguard Worker	addLabelsForInputs := func(propName string, include, exclude []string) android.Paths {
427*333d2b36SAndroid Build Coastguard Worker		includeDirInPaths := ctx.DeviceConfig().BuildBrokenInputDir(g.Name())
428*333d2b36SAndroid Build Coastguard Worker		var srcFiles android.Paths
429*333d2b36SAndroid Build Coastguard Worker		for _, in := range include {
430*333d2b36SAndroid Build Coastguard Worker			paths, missingDeps := android.PathsAndMissingDepsRelativeToModuleSourceDir(android.SourceInput{
431*333d2b36SAndroid Build Coastguard Worker				Context: ctx, Paths: []string{in}, ExcludePaths: exclude, IncludeDirs: includeDirInPaths,
432*333d2b36SAndroid Build Coastguard Worker			})
433*333d2b36SAndroid Build Coastguard Worker			if len(missingDeps) > 0 {
434*333d2b36SAndroid Build Coastguard Worker				if !ctx.Config().AllowMissingDependencies() {
435*333d2b36SAndroid Build Coastguard Worker					panic(fmt.Errorf("should never get here, the missing dependencies %q should have been reported in DepsMutator",
436*333d2b36SAndroid Build Coastguard Worker						missingDeps))
437*333d2b36SAndroid Build Coastguard Worker				}
438*333d2b36SAndroid Build Coastguard Worker
439*333d2b36SAndroid Build Coastguard Worker				// If AllowMissingDependencies is enabled, the build will not have stopped when
440*333d2b36SAndroid Build Coastguard Worker				// the dependency was added on a missing SourceFileProducer module, which will result in nonsensical
441*333d2b36SAndroid Build Coastguard Worker				// "cmd: label ":..." has no files" errors later.  Add a placeholder file to the local label.
442*333d2b36SAndroid Build Coastguard Worker				// The command that uses this placeholder file will never be executed because the rule will be
443*333d2b36SAndroid Build Coastguard Worker				// replaced with an android.Error rule reporting the missing dependencies.
444*333d2b36SAndroid Build Coastguard Worker				ctx.AddMissingDependencies(missingDeps)
445*333d2b36SAndroid Build Coastguard Worker				addLocationLabel(in, errorLocation{"***missing " + propName + " " + in + "***"})
446*333d2b36SAndroid Build Coastguard Worker			} else {
447*333d2b36SAndroid Build Coastguard Worker				srcFiles = append(srcFiles, paths...)
448*333d2b36SAndroid Build Coastguard Worker				addLocationLabel(in, inputLocation{paths})
449*333d2b36SAndroid Build Coastguard Worker			}
450*333d2b36SAndroid Build Coastguard Worker		}
451*333d2b36SAndroid Build Coastguard Worker		return srcFiles
452*333d2b36SAndroid Build Coastguard Worker	}
453*333d2b36SAndroid Build Coastguard Worker	srcs := g.properties.Srcs.GetOrDefault(ctx, nil)
454*333d2b36SAndroid Build Coastguard Worker	srcFiles := addLabelsForInputs("srcs", srcs, g.properties.Exclude_srcs)
455*333d2b36SAndroid Build Coastguard Worker	srcFiles = append(srcFiles, addLabelsForInputs("device_first_srcs", g.properties.Device_first_srcs.GetOrDefault(ctx, nil), nil)...)
456*333d2b36SAndroid Build Coastguard Worker	srcFiles = append(srcFiles, addLabelsForInputs("device_common_srcs", g.properties.Device_common_srcs.GetOrDefault(ctx, nil), nil)...)
457*333d2b36SAndroid Build Coastguard Worker	srcFiles = append(srcFiles, addLabelsForInputs("common_os_srcs", g.properties.Common_os_srcs.GetOrDefault(ctx, nil), nil)...)
458*333d2b36SAndroid Build Coastguard Worker	android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
459*333d2b36SAndroid Build Coastguard Worker
460*333d2b36SAndroid Build Coastguard Worker	var copyFrom android.Paths
461*333d2b36SAndroid Build Coastguard Worker	var outputFiles android.WritablePaths
462*333d2b36SAndroid Build Coastguard Worker	var zipArgs strings.Builder
463*333d2b36SAndroid Build Coastguard Worker
464*333d2b36SAndroid Build Coastguard Worker	cmd := g.properties.Cmd.GetOrDefault(ctx, "")
465*333d2b36SAndroid Build Coastguard Worker	if g.CmdModifier != nil {
466*333d2b36SAndroid Build Coastguard Worker		cmd = g.CmdModifier(ctx, cmd)
467*333d2b36SAndroid Build Coastguard Worker	}
468*333d2b36SAndroid Build Coastguard Worker
469*333d2b36SAndroid Build Coastguard Worker	var extraInputs android.Paths
470*333d2b36SAndroid Build Coastguard Worker	// Generate tasks, either from genrule or gensrcs.
471*333d2b36SAndroid Build Coastguard Worker	for i, task := range g.taskGenerator(ctx, cmd, srcFiles) {
472*333d2b36SAndroid Build Coastguard Worker		if len(task.out) == 0 {
473*333d2b36SAndroid Build Coastguard Worker			ctx.ModuleErrorf("must have at least one output file")
474*333d2b36SAndroid Build Coastguard Worker			return
475*333d2b36SAndroid Build Coastguard Worker		}
476*333d2b36SAndroid Build Coastguard Worker
477*333d2b36SAndroid Build Coastguard Worker		// Only handle extra inputs once as these currently are the same across all tasks
478*333d2b36SAndroid Build Coastguard Worker		if i == 0 {
479*333d2b36SAndroid Build Coastguard Worker			for name, values := range task.extraInputs {
480*333d2b36SAndroid Build Coastguard Worker				extraInputs = append(extraInputs, addLabelsForInputs(name, values, []string{})...)
481*333d2b36SAndroid Build Coastguard Worker			}
482*333d2b36SAndroid Build Coastguard Worker		}
483*333d2b36SAndroid Build Coastguard Worker
484*333d2b36SAndroid Build Coastguard Worker		// Pick a unique path outside the task.genDir for the sbox manifest textproto,
485*333d2b36SAndroid Build Coastguard Worker		// a unique rule name, and the user-visible description.
486*333d2b36SAndroid Build Coastguard Worker		var rule *android.RuleBuilder
487*333d2b36SAndroid Build Coastguard Worker		desc := "generate"
488*333d2b36SAndroid Build Coastguard Worker		name := "generator"
489*333d2b36SAndroid Build Coastguard Worker		if task.useNsjail {
490*333d2b36SAndroid Build Coastguard Worker			rule = android.NewRuleBuilder(pctx, ctx).Nsjail(task.genDir, android.PathForModuleOut(ctx, "nsjail_build_sandbox"))
491*333d2b36SAndroid Build Coastguard Worker			if task.keepGendir {
492*333d2b36SAndroid Build Coastguard Worker				rule.NsjailKeepGendir()
493*333d2b36SAndroid Build Coastguard Worker			}
494*333d2b36SAndroid Build Coastguard Worker		} else {
495*333d2b36SAndroid Build Coastguard Worker			manifestName := "genrule.sbox.textproto"
496*333d2b36SAndroid Build Coastguard Worker			if task.shards > 0 {
497*333d2b36SAndroid Build Coastguard Worker				manifestName = "genrule_" + strconv.Itoa(task.shard) + ".sbox.textproto"
498*333d2b36SAndroid Build Coastguard Worker				desc += " " + strconv.Itoa(task.shard)
499*333d2b36SAndroid Build Coastguard Worker				name += strconv.Itoa(task.shard)
500*333d2b36SAndroid Build Coastguard Worker			} else if len(task.out) == 1 {
501*333d2b36SAndroid Build Coastguard Worker				desc += " " + task.out[0].Base()
502*333d2b36SAndroid Build Coastguard Worker			}
503*333d2b36SAndroid Build Coastguard Worker
504*333d2b36SAndroid Build Coastguard Worker			manifestPath := android.PathForModuleOut(ctx, manifestName)
505*333d2b36SAndroid Build Coastguard Worker
506*333d2b36SAndroid Build Coastguard Worker			// Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
507*333d2b36SAndroid Build Coastguard Worker			rule = getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath))
508*333d2b36SAndroid Build Coastguard Worker		}
509*333d2b36SAndroid Build Coastguard Worker		if Bool(g.properties.Write_if_changed) {
510*333d2b36SAndroid Build Coastguard Worker			rule.Restat()
511*333d2b36SAndroid Build Coastguard Worker		}
512*333d2b36SAndroid Build Coastguard Worker		cmd := rule.Command()
513*333d2b36SAndroid Build Coastguard Worker
514*333d2b36SAndroid Build Coastguard Worker		for _, out := range task.out {
515*333d2b36SAndroid Build Coastguard Worker			addLocationLabel(out.Rel(), outputLocation{out})
516*333d2b36SAndroid Build Coastguard Worker		}
517*333d2b36SAndroid Build Coastguard Worker
518*333d2b36SAndroid Build Coastguard Worker		rawCommand, err := android.Expand(task.cmd, func(name string) (string, error) {
519*333d2b36SAndroid Build Coastguard Worker			// report the error directly without returning an error to android.Expand to catch multiple errors in a
520*333d2b36SAndroid Build Coastguard Worker			// single run
521*333d2b36SAndroid Build Coastguard Worker			reportError := func(fmt string, args ...interface{}) (string, error) {
522*333d2b36SAndroid Build Coastguard Worker				ctx.PropertyErrorf("cmd", fmt, args...)
523*333d2b36SAndroid Build Coastguard Worker				return "SOONG_ERROR", nil
524*333d2b36SAndroid Build Coastguard Worker			}
525*333d2b36SAndroid Build Coastguard Worker
526*333d2b36SAndroid Build Coastguard Worker			// Apply shell escape to each cases to prevent source file paths containing $ from being evaluated in shell
527*333d2b36SAndroid Build Coastguard Worker			switch name {
528*333d2b36SAndroid Build Coastguard Worker			case "location":
529*333d2b36SAndroid Build Coastguard Worker				if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 {
530*333d2b36SAndroid Build Coastguard Worker					return reportError("at least one `tools` or `tool_files` is required if $(location) is used")
531*333d2b36SAndroid Build Coastguard Worker				}
532*333d2b36SAndroid Build Coastguard Worker				loc := locationLabels[firstLabel]
533*333d2b36SAndroid Build Coastguard Worker				paths := loc.Paths(cmd)
534*333d2b36SAndroid Build Coastguard Worker				if len(paths) == 0 {
535*333d2b36SAndroid Build Coastguard Worker					return reportError("default label %q has no files", firstLabel)
536*333d2b36SAndroid Build Coastguard Worker				} else if len(paths) > 1 {
537*333d2b36SAndroid Build Coastguard Worker					return reportError("default label %q has multiple files, use $(locations %s) to reference it",
538*333d2b36SAndroid Build Coastguard Worker						firstLabel, firstLabel)
539*333d2b36SAndroid Build Coastguard Worker				}
540*333d2b36SAndroid Build Coastguard Worker				return proptools.ShellEscape(paths[0]), nil
541*333d2b36SAndroid Build Coastguard Worker			case "in":
542*333d2b36SAndroid Build Coastguard Worker				return strings.Join(proptools.ShellEscapeList(cmd.PathsForInputs(srcFiles)), " "), nil
543*333d2b36SAndroid Build Coastguard Worker			case "out":
544*333d2b36SAndroid Build Coastguard Worker				var sandboxOuts []string
545*333d2b36SAndroid Build Coastguard Worker				for _, out := range task.out {
546*333d2b36SAndroid Build Coastguard Worker					sandboxOuts = append(sandboxOuts, cmd.PathForOutput(out))
547*333d2b36SAndroid Build Coastguard Worker				}
548*333d2b36SAndroid Build Coastguard Worker				return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil
549*333d2b36SAndroid Build Coastguard Worker			case "genDir":
550*333d2b36SAndroid Build Coastguard Worker				return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil
551*333d2b36SAndroid Build Coastguard Worker			case "build_number_file":
552*333d2b36SAndroid Build Coastguard Worker				if !proptools.Bool(g.properties.Uses_order_only_build_number_file) {
553*333d2b36SAndroid Build Coastguard Worker					return reportError("to use the $(build_number_file) label, you must set uses_order_only_build_number_file: true")
554*333d2b36SAndroid Build Coastguard Worker				}
555*333d2b36SAndroid Build Coastguard Worker				return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildNumberFile(ctx))), nil
556*333d2b36SAndroid Build Coastguard Worker			default:
557*333d2b36SAndroid Build Coastguard Worker				if strings.HasPrefix(name, "location ") {
558*333d2b36SAndroid Build Coastguard Worker					label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
559*333d2b36SAndroid Build Coastguard Worker					if loc, ok := locationLabels[label]; ok {
560*333d2b36SAndroid Build Coastguard Worker						paths := loc.Paths(cmd)
561*333d2b36SAndroid Build Coastguard Worker						if len(paths) == 0 {
562*333d2b36SAndroid Build Coastguard Worker							return reportError("label %q has no files", label)
563*333d2b36SAndroid Build Coastguard Worker						} else if len(paths) > 1 {
564*333d2b36SAndroid Build Coastguard Worker							return reportError("label %q has multiple files, use $(locations %s) to reference it",
565*333d2b36SAndroid Build Coastguard Worker								label, label)
566*333d2b36SAndroid Build Coastguard Worker						}
567*333d2b36SAndroid Build Coastguard Worker						return proptools.ShellEscape(paths[0]), nil
568*333d2b36SAndroid Build Coastguard Worker					} else {
569*333d2b36SAndroid Build Coastguard Worker						return reportError("unknown location label %q is not in srcs, out, tools or tool_files.", label)
570*333d2b36SAndroid Build Coastguard Worker					}
571*333d2b36SAndroid Build Coastguard Worker				} else if strings.HasPrefix(name, "locations ") {
572*333d2b36SAndroid Build Coastguard Worker					label := strings.TrimSpace(strings.TrimPrefix(name, "locations "))
573*333d2b36SAndroid Build Coastguard Worker					if loc, ok := locationLabels[label]; ok {
574*333d2b36SAndroid Build Coastguard Worker						paths := loc.Paths(cmd)
575*333d2b36SAndroid Build Coastguard Worker						if len(paths) == 0 {
576*333d2b36SAndroid Build Coastguard Worker							return reportError("label %q has no files", label)
577*333d2b36SAndroid Build Coastguard Worker						}
578*333d2b36SAndroid Build Coastguard Worker						return strings.Join(proptools.ShellEscapeList(paths), " "), nil
579*333d2b36SAndroid Build Coastguard Worker					} else {
580*333d2b36SAndroid Build Coastguard Worker						return reportError("unknown locations label %q is not in srcs, out, tools or tool_files.", label)
581*333d2b36SAndroid Build Coastguard Worker					}
582*333d2b36SAndroid Build Coastguard Worker				} else {
583*333d2b36SAndroid Build Coastguard Worker					return reportError("unknown variable '$(%s)'", name)
584*333d2b36SAndroid Build Coastguard Worker				}
585*333d2b36SAndroid Build Coastguard Worker			}
586*333d2b36SAndroid Build Coastguard Worker		})
587*333d2b36SAndroid Build Coastguard Worker
588*333d2b36SAndroid Build Coastguard Worker		if err != nil {
589*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("cmd", "%s", err.Error())
590*333d2b36SAndroid Build Coastguard Worker			return
591*333d2b36SAndroid Build Coastguard Worker		}
592*333d2b36SAndroid Build Coastguard Worker
593*333d2b36SAndroid Build Coastguard Worker		g.rawCommands = append(g.rawCommands, rawCommand)
594*333d2b36SAndroid Build Coastguard Worker
595*333d2b36SAndroid Build Coastguard Worker		cmd.Text(rawCommand)
596*333d2b36SAndroid Build Coastguard Worker		cmd.Implicits(srcFiles) // need to be able to reference other srcs
597*333d2b36SAndroid Build Coastguard Worker		cmd.Implicits(extraInputs)
598*333d2b36SAndroid Build Coastguard Worker		cmd.ImplicitOutputs(task.out)
599*333d2b36SAndroid Build Coastguard Worker		cmd.Implicits(task.in)
600*333d2b36SAndroid Build Coastguard Worker		cmd.ImplicitTools(tools)
601*333d2b36SAndroid Build Coastguard Worker		cmd.ImplicitPackagedTools(packagedTools)
602*333d2b36SAndroid Build Coastguard Worker		if proptools.Bool(g.properties.Uses_order_only_build_number_file) {
603*333d2b36SAndroid Build Coastguard Worker			if !isModuleInBuildNumberAllowlist(ctx) {
604*333d2b36SAndroid Build Coastguard Worker				ctx.ModuleErrorf("Only allowlisted modules may use uses_order_only_build_number_file: true")
605*333d2b36SAndroid Build Coastguard Worker			}
606*333d2b36SAndroid Build Coastguard Worker			cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx))
607*333d2b36SAndroid Build Coastguard Worker		}
608*333d2b36SAndroid Build Coastguard Worker
609*333d2b36SAndroid Build Coastguard Worker		if task.useNsjail {
610*333d2b36SAndroid Build Coastguard Worker			for _, input := range task.dirSrcs {
611*333d2b36SAndroid Build Coastguard Worker				cmd.ImplicitDirectory(input)
612*333d2b36SAndroid Build Coastguard Worker				// TODO(b/375551969): remove glob
613*333d2b36SAndroid Build Coastguard Worker				if paths, err := ctx.GlobWithDeps(filepath.Join(input.String(), "**/*"), nil); err == nil {
614*333d2b36SAndroid Build Coastguard Worker					rule.NsjailImplicits(android.PathsForSource(ctx, paths))
615*333d2b36SAndroid Build Coastguard Worker				} else {
616*333d2b36SAndroid Build Coastguard Worker					ctx.PropertyErrorf("dir_srcs", "can't glob %q", input.String())
617*333d2b36SAndroid Build Coastguard Worker				}
618*333d2b36SAndroid Build Coastguard Worker			}
619*333d2b36SAndroid Build Coastguard Worker		}
620*333d2b36SAndroid Build Coastguard Worker
621*333d2b36SAndroid Build Coastguard Worker		// Create the rule to run the genrule command inside sbox.
622*333d2b36SAndroid Build Coastguard Worker		rule.Build(name, desc)
623*333d2b36SAndroid Build Coastguard Worker
624*333d2b36SAndroid Build Coastguard Worker		if len(task.copyTo) > 0 {
625*333d2b36SAndroid Build Coastguard Worker			// If copyTo is set, multiple shards need to be copied into a single directory.
626*333d2b36SAndroid Build Coastguard Worker			// task.out contains the per-shard paths, and copyTo contains the corresponding
627*333d2b36SAndroid Build Coastguard Worker			// final path.  The files need to be copied into the final directory by a
628*333d2b36SAndroid Build Coastguard Worker			// single rule so it can remove the directory before it starts to ensure no
629*333d2b36SAndroid Build Coastguard Worker			// old files remain.  zipsync already does this, so build up zipArgs that
630*333d2b36SAndroid Build Coastguard Worker			// zip all the per-shard directories into a single zip.
631*333d2b36SAndroid Build Coastguard Worker			outputFiles = append(outputFiles, task.copyTo...)
632*333d2b36SAndroid Build Coastguard Worker			copyFrom = append(copyFrom, task.out.Paths()...)
633*333d2b36SAndroid Build Coastguard Worker			zipArgs.WriteString(" -C " + task.genDir.String())
634*333d2b36SAndroid Build Coastguard Worker			zipArgs.WriteString(android.JoinWithPrefix(task.out.Strings(), " -f "))
635*333d2b36SAndroid Build Coastguard Worker		} else {
636*333d2b36SAndroid Build Coastguard Worker			outputFiles = append(outputFiles, task.out...)
637*333d2b36SAndroid Build Coastguard Worker		}
638*333d2b36SAndroid Build Coastguard Worker	}
639*333d2b36SAndroid Build Coastguard Worker
640*333d2b36SAndroid Build Coastguard Worker	if len(copyFrom) > 0 {
641*333d2b36SAndroid Build Coastguard Worker		// Create a rule that zips all the per-shard directories into a single zip and then
642*333d2b36SAndroid Build Coastguard Worker		// uses zipsync to unzip it into the final directory.
643*333d2b36SAndroid Build Coastguard Worker		ctx.Build(pctx, android.BuildParams{
644*333d2b36SAndroid Build Coastguard Worker			Rule:        gensrcsMerge,
645*333d2b36SAndroid Build Coastguard Worker			Implicits:   copyFrom,
646*333d2b36SAndroid Build Coastguard Worker			Outputs:     outputFiles,
647*333d2b36SAndroid Build Coastguard Worker			Description: "merge shards",
648*333d2b36SAndroid Build Coastguard Worker			Args: map[string]string{
649*333d2b36SAndroid Build Coastguard Worker				"zipArgs": zipArgs.String(),
650*333d2b36SAndroid Build Coastguard Worker				"tmpZip":  android.PathForModuleGen(ctx, g.subDir+".zip").String(),
651*333d2b36SAndroid Build Coastguard Worker				"genDir":  android.PathForModuleGen(ctx, g.subDir).String(),
652*333d2b36SAndroid Build Coastguard Worker			},
653*333d2b36SAndroid Build Coastguard Worker		})
654*333d2b36SAndroid Build Coastguard Worker	}
655*333d2b36SAndroid Build Coastguard Worker
656*333d2b36SAndroid Build Coastguard Worker	g.outputFiles = outputFiles.Paths()
657*333d2b36SAndroid Build Coastguard Worker}
658*333d2b36SAndroid Build Coastguard Worker
659*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
660*333d2b36SAndroid Build Coastguard Worker	g.generateCommonBuildActions(ctx)
661*333d2b36SAndroid Build Coastguard Worker
662*333d2b36SAndroid Build Coastguard Worker	// For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
663*333d2b36SAndroid Build Coastguard Worker	// the genrules on AOSP. That will make things simpler to look at the graph in the common
664*333d2b36SAndroid Build Coastguard Worker	// case. For larger sets of outputs, inject a phony target in between to limit ninja file
665*333d2b36SAndroid Build Coastguard Worker	// growth.
666*333d2b36SAndroid Build Coastguard Worker	if len(g.outputFiles) <= 6 {
667*333d2b36SAndroid Build Coastguard Worker		g.outputDeps = g.outputFiles
668*333d2b36SAndroid Build Coastguard Worker	} else {
669*333d2b36SAndroid Build Coastguard Worker		phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
670*333d2b36SAndroid Build Coastguard Worker		ctx.Build(pctx, android.BuildParams{
671*333d2b36SAndroid Build Coastguard Worker			Rule:   blueprint.Phony,
672*333d2b36SAndroid Build Coastguard Worker			Output: phonyFile,
673*333d2b36SAndroid Build Coastguard Worker			Inputs: g.outputFiles,
674*333d2b36SAndroid Build Coastguard Worker		})
675*333d2b36SAndroid Build Coastguard Worker		g.outputDeps = android.Paths{phonyFile}
676*333d2b36SAndroid Build Coastguard Worker	}
677*333d2b36SAndroid Build Coastguard Worker
678*333d2b36SAndroid Build Coastguard Worker	g.setOutputFiles(ctx)
679*333d2b36SAndroid Build Coastguard Worker
680*333d2b36SAndroid Build Coastguard Worker	if ctx.Os() == android.Windows {
681*333d2b36SAndroid Build Coastguard Worker		// Make doesn't support windows:
682*333d2b36SAndroid Build Coastguard Worker		// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/module_arch_supported.mk;l=66;drc=f264690860bb6ee7762784d6b7201aae057ba6f2
683*333d2b36SAndroid Build Coastguard Worker		g.HideFromMake()
684*333d2b36SAndroid Build Coastguard Worker	}
685*333d2b36SAndroid Build Coastguard Worker}
686*333d2b36SAndroid Build Coastguard Worker
687*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) setOutputFiles(ctx android.ModuleContext) {
688*333d2b36SAndroid Build Coastguard Worker	if len(g.outputFiles) == 0 {
689*333d2b36SAndroid Build Coastguard Worker		return
690*333d2b36SAndroid Build Coastguard Worker	}
691*333d2b36SAndroid Build Coastguard Worker	ctx.SetOutputFiles(g.outputFiles, "")
692*333d2b36SAndroid Build Coastguard Worker	// non-empty-string-tag should match one of the outputs
693*333d2b36SAndroid Build Coastguard Worker	for _, files := range g.outputFiles {
694*333d2b36SAndroid Build Coastguard Worker		ctx.SetOutputFiles(android.Paths{files}, files.Rel())
695*333d2b36SAndroid Build Coastguard Worker	}
696*333d2b36SAndroid Build Coastguard Worker}
697*333d2b36SAndroid Build Coastguard Worker
698*333d2b36SAndroid Build Coastguard Worker// Collect information for opening IDE project files in java/jdeps.go.
699*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
700*333d2b36SAndroid Build Coastguard Worker	dpInfo.Srcs = append(dpInfo.Srcs, g.Srcs().Strings()...)
701*333d2b36SAndroid Build Coastguard Worker	for _, src := range g.properties.Srcs.GetOrDefault(ctx, nil) {
702*333d2b36SAndroid Build Coastguard Worker		if strings.HasPrefix(src, ":") {
703*333d2b36SAndroid Build Coastguard Worker			src = strings.Trim(src, ":")
704*333d2b36SAndroid Build Coastguard Worker			dpInfo.Deps = append(dpInfo.Deps, src)
705*333d2b36SAndroid Build Coastguard Worker		}
706*333d2b36SAndroid Build Coastguard Worker	}
707*333d2b36SAndroid Build Coastguard Worker}
708*333d2b36SAndroid Build Coastguard Worker
709*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) AndroidMk() android.AndroidMkData {
710*333d2b36SAndroid Build Coastguard Worker	return android.AndroidMkData{
711*333d2b36SAndroid Build Coastguard Worker		Class:      "ETC",
712*333d2b36SAndroid Build Coastguard Worker		OutputFile: android.OptionalPathForPath(g.outputFiles[0]),
713*333d2b36SAndroid Build Coastguard Worker		SubName:    g.subName,
714*333d2b36SAndroid Build Coastguard Worker		Extra: []android.AndroidMkExtraFunc{
715*333d2b36SAndroid Build Coastguard Worker			func(w io.Writer, outputFile android.Path) {
716*333d2b36SAndroid Build Coastguard Worker				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
717*333d2b36SAndroid Build Coastguard Worker			},
718*333d2b36SAndroid Build Coastguard Worker		},
719*333d2b36SAndroid Build Coastguard Worker		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
720*333d2b36SAndroid Build Coastguard Worker			android.WriteAndroidMkData(w, data)
721*333d2b36SAndroid Build Coastguard Worker			if data.SubName != "" {
722*333d2b36SAndroid Build Coastguard Worker				fmt.Fprintln(w, ".PHONY:", name)
723*333d2b36SAndroid Build Coastguard Worker				fmt.Fprintln(w, name, ":", name+g.subName)
724*333d2b36SAndroid Build Coastguard Worker			}
725*333d2b36SAndroid Build Coastguard Worker		},
726*333d2b36SAndroid Build Coastguard Worker	}
727*333d2b36SAndroid Build Coastguard Worker}
728*333d2b36SAndroid Build Coastguard Worker
729*333d2b36SAndroid Build Coastguard Workervar _ android.ApexModule = (*Module)(nil)
730*333d2b36SAndroid Build Coastguard Worker
731*333d2b36SAndroid Build Coastguard Worker// Implements android.ApexModule
732*333d2b36SAndroid Build Coastguard Workerfunc (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
733*333d2b36SAndroid Build Coastguard Worker	sdkVersion android.ApiLevel) error {
734*333d2b36SAndroid Build Coastguard Worker	// Because generated outputs are checked by client modules(e.g. cc_library, ...)
735*333d2b36SAndroid Build Coastguard Worker	// we can safely ignore the check here.
736*333d2b36SAndroid Build Coastguard Worker	return nil
737*333d2b36SAndroid Build Coastguard Worker}
738*333d2b36SAndroid Build Coastguard Worker
739*333d2b36SAndroid Build Coastguard Workerfunc generatorFactory(taskGenerator taskFunc, props ...interface{}) *Module {
740*333d2b36SAndroid Build Coastguard Worker	module := &Module{
741*333d2b36SAndroid Build Coastguard Worker		taskGenerator: taskGenerator,
742*333d2b36SAndroid Build Coastguard Worker	}
743*333d2b36SAndroid Build Coastguard Worker
744*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(props...)
745*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(&module.properties)
746*333d2b36SAndroid Build Coastguard Worker
747*333d2b36SAndroid Build Coastguard Worker	module.ImageInterface = noopImageInterface{}
748*333d2b36SAndroid Build Coastguard Worker
749*333d2b36SAndroid Build Coastguard Worker	return module
750*333d2b36SAndroid Build Coastguard Worker}
751*333d2b36SAndroid Build Coastguard Worker
752*333d2b36SAndroid Build Coastguard Workertype noopImageInterface struct{}
753*333d2b36SAndroid Build Coastguard Worker
754*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) ImageMutatorBegin(android.ImageInterfaceContext)         {}
755*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) VendorVariantNeeded(android.ImageInterfaceContext) bool  { return false }
756*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) ProductVariantNeeded(android.ImageInterfaceContext) bool { return false }
757*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) CoreVariantNeeded(android.ImageInterfaceContext) bool    { return false }
758*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) RamdiskVariantNeeded(android.ImageInterfaceContext) bool { return false }
759*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) VendorRamdiskVariantNeeded(android.ImageInterfaceContext) bool {
760*333d2b36SAndroid Build Coastguard Worker	return false
761*333d2b36SAndroid Build Coastguard Worker}
762*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) DebugRamdiskVariantNeeded(android.ImageInterfaceContext) bool {
763*333d2b36SAndroid Build Coastguard Worker	return false
764*333d2b36SAndroid Build Coastguard Worker}
765*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) RecoveryVariantNeeded(android.ImageInterfaceContext) bool { return false }
766*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
767*333d2b36SAndroid Build Coastguard Worker	return nil
768*333d2b36SAndroid Build Coastguard Worker}
769*333d2b36SAndroid Build Coastguard Workerfunc (x noopImageInterface) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
770*333d2b36SAndroid Build Coastguard Worker}
771*333d2b36SAndroid Build Coastguard Worker
772*333d2b36SAndroid Build Coastguard Workerfunc NewGenSrcs() *Module {
773*333d2b36SAndroid Build Coastguard Worker	properties := &genSrcsProperties{}
774*333d2b36SAndroid Build Coastguard Worker
775*333d2b36SAndroid Build Coastguard Worker	// finalSubDir is the name of the subdirectory that output files will be generated into.
776*333d2b36SAndroid Build Coastguard Worker	// It is used so that per-shard directories can be placed alongside it an then finally
777*333d2b36SAndroid Build Coastguard Worker	// merged into it.
778*333d2b36SAndroid Build Coastguard Worker	const finalSubDir = "gensrcs"
779*333d2b36SAndroid Build Coastguard Worker
780*333d2b36SAndroid Build Coastguard Worker	taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
781*333d2b36SAndroid Build Coastguard Worker		shardSize := defaultShardSize
782*333d2b36SAndroid Build Coastguard Worker		if s := properties.Shard_size; s != nil {
783*333d2b36SAndroid Build Coastguard Worker			shardSize = int(*s)
784*333d2b36SAndroid Build Coastguard Worker		}
785*333d2b36SAndroid Build Coastguard Worker
786*333d2b36SAndroid Build Coastguard Worker		// gensrcs rules can easily hit command line limits by repeating the command for
787*333d2b36SAndroid Build Coastguard Worker		// every input file.  Shard the input files into groups.
788*333d2b36SAndroid Build Coastguard Worker		shards := android.ShardPaths(srcFiles, shardSize)
789*333d2b36SAndroid Build Coastguard Worker		var generateTasks []generateTask
790*333d2b36SAndroid Build Coastguard Worker
791*333d2b36SAndroid Build Coastguard Worker		for i, shard := range shards {
792*333d2b36SAndroid Build Coastguard Worker			var commands []string
793*333d2b36SAndroid Build Coastguard Worker			var outFiles android.WritablePaths
794*333d2b36SAndroid Build Coastguard Worker			var copyTo android.WritablePaths
795*333d2b36SAndroid Build Coastguard Worker
796*333d2b36SAndroid Build Coastguard Worker			// When sharding is enabled (i.e. len(shards) > 1), the sbox rules for each
797*333d2b36SAndroid Build Coastguard Worker			// shard will be write to their own directories and then be merged together
798*333d2b36SAndroid Build Coastguard Worker			// into finalSubDir.  If sharding is not enabled (i.e. len(shards) == 1),
799*333d2b36SAndroid Build Coastguard Worker			// the sbox rule will write directly to finalSubDir.
800*333d2b36SAndroid Build Coastguard Worker			genSubDir := finalSubDir
801*333d2b36SAndroid Build Coastguard Worker			if len(shards) > 1 {
802*333d2b36SAndroid Build Coastguard Worker				genSubDir = strconv.Itoa(i)
803*333d2b36SAndroid Build Coastguard Worker			}
804*333d2b36SAndroid Build Coastguard Worker
805*333d2b36SAndroid Build Coastguard Worker			genDir := android.PathForModuleGen(ctx, genSubDir)
806*333d2b36SAndroid Build Coastguard Worker			// TODO(ccross): this RuleBuilder is a hack to be able to call
807*333d2b36SAndroid Build Coastguard Worker			// rule.Command().PathForOutput.  Replace this with passing the rule into the
808*333d2b36SAndroid Build Coastguard Worker			// generator.
809*333d2b36SAndroid Build Coastguard Worker			rule := getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(genDir, nil))
810*333d2b36SAndroid Build Coastguard Worker
811*333d2b36SAndroid Build Coastguard Worker			for _, in := range shard {
812*333d2b36SAndroid Build Coastguard Worker				outFile := android.GenPathWithExtAndTrimExt(ctx, finalSubDir, in, String(properties.Output_extension), String(properties.Trim_extension))
813*333d2b36SAndroid Build Coastguard Worker
814*333d2b36SAndroid Build Coastguard Worker				// If sharding is enabled, then outFile is the path to the output file in
815*333d2b36SAndroid Build Coastguard Worker				// the shard directory, and copyTo is the path to the output file in the
816*333d2b36SAndroid Build Coastguard Worker				// final directory.
817*333d2b36SAndroid Build Coastguard Worker				if len(shards) > 1 {
818*333d2b36SAndroid Build Coastguard Worker					shardFile := android.GenPathWithExtAndTrimExt(ctx, genSubDir, in, String(properties.Output_extension), String(properties.Trim_extension))
819*333d2b36SAndroid Build Coastguard Worker					copyTo = append(copyTo, outFile)
820*333d2b36SAndroid Build Coastguard Worker					outFile = shardFile
821*333d2b36SAndroid Build Coastguard Worker				}
822*333d2b36SAndroid Build Coastguard Worker
823*333d2b36SAndroid Build Coastguard Worker				outFiles = append(outFiles, outFile)
824*333d2b36SAndroid Build Coastguard Worker
825*333d2b36SAndroid Build Coastguard Worker				// pre-expand the command line to replace $in and $out with references to
826*333d2b36SAndroid Build Coastguard Worker				// a single input and output file.
827*333d2b36SAndroid Build Coastguard Worker				command, err := android.Expand(rawCommand, func(name string) (string, error) {
828*333d2b36SAndroid Build Coastguard Worker					switch name {
829*333d2b36SAndroid Build Coastguard Worker					case "in":
830*333d2b36SAndroid Build Coastguard Worker						return in.String(), nil
831*333d2b36SAndroid Build Coastguard Worker					case "out":
832*333d2b36SAndroid Build Coastguard Worker						return rule.Command().PathForOutput(outFile), nil
833*333d2b36SAndroid Build Coastguard Worker					default:
834*333d2b36SAndroid Build Coastguard Worker						return "$(" + name + ")", nil
835*333d2b36SAndroid Build Coastguard Worker					}
836*333d2b36SAndroid Build Coastguard Worker				})
837*333d2b36SAndroid Build Coastguard Worker				if err != nil {
838*333d2b36SAndroid Build Coastguard Worker					ctx.PropertyErrorf("cmd", err.Error())
839*333d2b36SAndroid Build Coastguard Worker				}
840*333d2b36SAndroid Build Coastguard Worker
841*333d2b36SAndroid Build Coastguard Worker				// escape the command in case for example it contains '#', an odd number of '"', etc
842*333d2b36SAndroid Build Coastguard Worker				command = fmt.Sprintf("bash -c %v", proptools.ShellEscape(command))
843*333d2b36SAndroid Build Coastguard Worker				commands = append(commands, command)
844*333d2b36SAndroid Build Coastguard Worker			}
845*333d2b36SAndroid Build Coastguard Worker			fullCommand := strings.Join(commands, " && ")
846*333d2b36SAndroid Build Coastguard Worker
847*333d2b36SAndroid Build Coastguard Worker			generateTasks = append(generateTasks, generateTask{
848*333d2b36SAndroid Build Coastguard Worker				in:     shard,
849*333d2b36SAndroid Build Coastguard Worker				out:    outFiles,
850*333d2b36SAndroid Build Coastguard Worker				copyTo: copyTo,
851*333d2b36SAndroid Build Coastguard Worker				genDir: genDir,
852*333d2b36SAndroid Build Coastguard Worker				cmd:    fullCommand,
853*333d2b36SAndroid Build Coastguard Worker				shard:  i,
854*333d2b36SAndroid Build Coastguard Worker				shards: len(shards),
855*333d2b36SAndroid Build Coastguard Worker				extraInputs: map[string][]string{
856*333d2b36SAndroid Build Coastguard Worker					"data": properties.Data,
857*333d2b36SAndroid Build Coastguard Worker				},
858*333d2b36SAndroid Build Coastguard Worker			})
859*333d2b36SAndroid Build Coastguard Worker		}
860*333d2b36SAndroid Build Coastguard Worker
861*333d2b36SAndroid Build Coastguard Worker		return generateTasks
862*333d2b36SAndroid Build Coastguard Worker	}
863*333d2b36SAndroid Build Coastguard Worker
864*333d2b36SAndroid Build Coastguard Worker	g := generatorFactory(taskGenerator, properties)
865*333d2b36SAndroid Build Coastguard Worker	g.subDir = finalSubDir
866*333d2b36SAndroid Build Coastguard Worker	return g
867*333d2b36SAndroid Build Coastguard Worker}
868*333d2b36SAndroid Build Coastguard Worker
869*333d2b36SAndroid Build Coastguard Workerfunc GenSrcsFactory() android.Module {
870*333d2b36SAndroid Build Coastguard Worker	m := NewGenSrcs()
871*333d2b36SAndroid Build Coastguard Worker	android.InitAndroidModule(m)
872*333d2b36SAndroid Build Coastguard Worker	android.InitDefaultableModule(m)
873*333d2b36SAndroid Build Coastguard Worker	return m
874*333d2b36SAndroid Build Coastguard Worker}
875*333d2b36SAndroid Build Coastguard Worker
876*333d2b36SAndroid Build Coastguard Workertype genSrcsProperties struct {
877*333d2b36SAndroid Build Coastguard Worker	// extension that will be substituted for each output file
878*333d2b36SAndroid Build Coastguard Worker	Output_extension *string
879*333d2b36SAndroid Build Coastguard Worker
880*333d2b36SAndroid Build Coastguard Worker	// maximum number of files that will be passed on a single command line.
881*333d2b36SAndroid Build Coastguard Worker	Shard_size *int64
882*333d2b36SAndroid Build Coastguard Worker
883*333d2b36SAndroid Build Coastguard Worker	// Additional files needed for build that are not tooling related.
884*333d2b36SAndroid Build Coastguard Worker	Data []string `android:"path"`
885*333d2b36SAndroid Build Coastguard Worker
886*333d2b36SAndroid Build Coastguard Worker	// Trim the matched extension for each input file, and it should start with ".".
887*333d2b36SAndroid Build Coastguard Worker	Trim_extension *string
888*333d2b36SAndroid Build Coastguard Worker}
889*333d2b36SAndroid Build Coastguard Worker
890*333d2b36SAndroid Build Coastguard Workerconst defaultShardSize = 50
891*333d2b36SAndroid Build Coastguard Worker
892*333d2b36SAndroid Build Coastguard Workerfunc NewGenRule() *Module {
893*333d2b36SAndroid Build Coastguard Worker	properties := &genRuleProperties{}
894*333d2b36SAndroid Build Coastguard Worker
895*333d2b36SAndroid Build Coastguard Worker	taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
896*333d2b36SAndroid Build Coastguard Worker		useNsjail := Bool(properties.Use_nsjail)
897*333d2b36SAndroid Build Coastguard Worker
898*333d2b36SAndroid Build Coastguard Worker		dirSrcs := android.DirectoryPathsForModuleSrc(ctx, properties.Dir_srcs)
899*333d2b36SAndroid Build Coastguard Worker		if len(dirSrcs) > 0 && !useNsjail {
900*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("dir_srcs", "can't use dir_srcs if use_nsjail is false")
901*333d2b36SAndroid Build Coastguard Worker			return nil
902*333d2b36SAndroid Build Coastguard Worker		}
903*333d2b36SAndroid Build Coastguard Worker
904*333d2b36SAndroid Build Coastguard Worker		keepGendir := Bool(properties.Keep_gendir)
905*333d2b36SAndroid Build Coastguard Worker		if keepGendir && !useNsjail {
906*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("keep_gendir", "can't use keep_gendir if use_nsjail is false")
907*333d2b36SAndroid Build Coastguard Worker			return nil
908*333d2b36SAndroid Build Coastguard Worker		}
909*333d2b36SAndroid Build Coastguard Worker
910*333d2b36SAndroid Build Coastguard Worker		outs := make(android.WritablePaths, len(properties.Out))
911*333d2b36SAndroid Build Coastguard Worker		for i, out := range properties.Out {
912*333d2b36SAndroid Build Coastguard Worker			outs[i] = android.PathForModuleGen(ctx, out)
913*333d2b36SAndroid Build Coastguard Worker		}
914*333d2b36SAndroid Build Coastguard Worker		return []generateTask{{
915*333d2b36SAndroid Build Coastguard Worker			in:         srcFiles,
916*333d2b36SAndroid Build Coastguard Worker			out:        outs,
917*333d2b36SAndroid Build Coastguard Worker			genDir:     android.PathForModuleGen(ctx),
918*333d2b36SAndroid Build Coastguard Worker			cmd:        rawCommand,
919*333d2b36SAndroid Build Coastguard Worker			useNsjail:  useNsjail,
920*333d2b36SAndroid Build Coastguard Worker			dirSrcs:    dirSrcs,
921*333d2b36SAndroid Build Coastguard Worker			keepGendir: keepGendir,
922*333d2b36SAndroid Build Coastguard Worker		}}
923*333d2b36SAndroid Build Coastguard Worker	}
924*333d2b36SAndroid Build Coastguard Worker
925*333d2b36SAndroid Build Coastguard Worker	return generatorFactory(taskGenerator, properties)
926*333d2b36SAndroid Build Coastguard Worker}
927*333d2b36SAndroid Build Coastguard Worker
928*333d2b36SAndroid Build Coastguard Workerfunc GenRuleFactory() android.Module {
929*333d2b36SAndroid Build Coastguard Worker	m := NewGenRule()
930*333d2b36SAndroid Build Coastguard Worker	android.InitAndroidModule(m)
931*333d2b36SAndroid Build Coastguard Worker	android.InitDefaultableModule(m)
932*333d2b36SAndroid Build Coastguard Worker	return m
933*333d2b36SAndroid Build Coastguard Worker}
934*333d2b36SAndroid Build Coastguard Worker
935*333d2b36SAndroid Build Coastguard Workertype genRuleProperties struct {
936*333d2b36SAndroid Build Coastguard Worker	Use_nsjail *bool
937*333d2b36SAndroid Build Coastguard Worker
938*333d2b36SAndroid Build Coastguard Worker	// List of input directories. Can be set only when use_nsjail is true. Currently, usage of
939*333d2b36SAndroid Build Coastguard Worker	// dir_srcs is limited only to Trusty build.
940*333d2b36SAndroid Build Coastguard Worker	Dir_srcs []string `android:"path"`
941*333d2b36SAndroid Build Coastguard Worker
942*333d2b36SAndroid Build Coastguard Worker	// If set to true, $(genDir) is not truncated. Useful when this genrule can be incrementally
943*333d2b36SAndroid Build Coastguard Worker	// built. Can be set only when use_nsjail is true.
944*333d2b36SAndroid Build Coastguard Worker	Keep_gendir *bool
945*333d2b36SAndroid Build Coastguard Worker
946*333d2b36SAndroid Build Coastguard Worker	// names of the output files that will be generated
947*333d2b36SAndroid Build Coastguard Worker	Out []string `android:"arch_variant"`
948*333d2b36SAndroid Build Coastguard Worker}
949*333d2b36SAndroid Build Coastguard Worker
950*333d2b36SAndroid Build Coastguard Workervar Bool = proptools.Bool
951*333d2b36SAndroid Build Coastguard Workervar String = proptools.String
952*333d2b36SAndroid Build Coastguard Worker
953*333d2b36SAndroid Build Coastguard Worker// Defaults
954*333d2b36SAndroid Build Coastguard Workertype Defaults struct {
955*333d2b36SAndroid Build Coastguard Worker	android.ModuleBase
956*333d2b36SAndroid Build Coastguard Worker	android.DefaultsModuleBase
957*333d2b36SAndroid Build Coastguard Worker}
958*333d2b36SAndroid Build Coastguard Worker
959*333d2b36SAndroid Build Coastguard Workerfunc defaultsFactory() android.Module {
960*333d2b36SAndroid Build Coastguard Worker	return DefaultsFactory()
961*333d2b36SAndroid Build Coastguard Worker}
962*333d2b36SAndroid Build Coastguard Worker
963*333d2b36SAndroid Build Coastguard Workerfunc DefaultsFactory(props ...interface{}) android.Module {
964*333d2b36SAndroid Build Coastguard Worker	module := &Defaults{}
965*333d2b36SAndroid Build Coastguard Worker
966*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(props...)
967*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(
968*333d2b36SAndroid Build Coastguard Worker		&generatorProperties{},
969*333d2b36SAndroid Build Coastguard Worker		&genRuleProperties{},
970*333d2b36SAndroid Build Coastguard Worker	)
971*333d2b36SAndroid Build Coastguard Worker
972*333d2b36SAndroid Build Coastguard Worker	android.InitDefaultsModule(module)
973*333d2b36SAndroid Build Coastguard Worker
974*333d2b36SAndroid Build Coastguard Worker	return module
975*333d2b36SAndroid Build Coastguard Worker}
976*333d2b36SAndroid Build Coastguard Worker
977*333d2b36SAndroid Build Coastguard Workervar sandboxingAllowlistKey = android.NewOnceKey("genruleSandboxingAllowlistKey")
978*333d2b36SAndroid Build Coastguard Worker
979*333d2b36SAndroid Build Coastguard Workertype sandboxingAllowlistSets struct {
980*333d2b36SAndroid Build Coastguard Worker	sandboxingDenyModuleSet map[string]bool
981*333d2b36SAndroid Build Coastguard Worker}
982*333d2b36SAndroid Build Coastguard Worker
983*333d2b36SAndroid Build Coastguard Workerfunc getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSets {
984*333d2b36SAndroid Build Coastguard Worker	return ctx.Config().Once(sandboxingAllowlistKey, func() interface{} {
985*333d2b36SAndroid Build Coastguard Worker		sandboxingDenyModuleSet := map[string]bool{}
986*333d2b36SAndroid Build Coastguard Worker
987*333d2b36SAndroid Build Coastguard Worker		android.AddToStringSet(sandboxingDenyModuleSet, SandboxingDenyModuleList)
988*333d2b36SAndroid Build Coastguard Worker		return &sandboxingAllowlistSets{
989*333d2b36SAndroid Build Coastguard Worker			sandboxingDenyModuleSet: sandboxingDenyModuleSet,
990*333d2b36SAndroid Build Coastguard Worker		}
991*333d2b36SAndroid Build Coastguard Worker	}).(*sandboxingAllowlistSets)
992*333d2b36SAndroid Build Coastguard Worker}
993*333d2b36SAndroid Build Coastguard Worker
994*333d2b36SAndroid Build Coastguard Workerfunc getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
995*333d2b36SAndroid Build Coastguard Worker	if !ctx.DeviceConfig().GenruleSandboxing() {
996*333d2b36SAndroid Build Coastguard Worker		return r.SandboxTools()
997*333d2b36SAndroid Build Coastguard Worker	}
998*333d2b36SAndroid Build Coastguard Worker	sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx)
999*333d2b36SAndroid Build Coastguard Worker	if sandboxingAllowlistSets.sandboxingDenyModuleSet[ctx.ModuleName()] {
1000*333d2b36SAndroid Build Coastguard Worker		return r.SandboxTools()
1001*333d2b36SAndroid Build Coastguard Worker	}
1002*333d2b36SAndroid Build Coastguard Worker	return r.SandboxInputs()
1003*333d2b36SAndroid Build Coastguard Worker}
1004