xref: /aosp_15_r20/build/soong/cc/builder.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2015 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 cc
16
17// This file generates the final rules for compiling all C/C++.  All properties related to
18// compiling should have been translated into builderFlags or another argument to the Transform*
19// functions.
20
21import (
22	"fmt"
23	"path/filepath"
24	"runtime"
25	"slices"
26	"strconv"
27	"strings"
28
29	"github.com/google/blueprint"
30	"github.com/google/blueprint/pathtools"
31
32	"android/soong/android"
33	"android/soong/cc/config"
34	"android/soong/remoteexec"
35)
36
37const (
38	objectExtension        = ".o"
39	staticLibraryExtension = ".a"
40)
41
42var (
43	pctx = android.NewPackageContext("android/soong/cc")
44
45	// Rule to invoke gcc with given command, flags, and dependencies. Outputs a .d depfile.
46	cc = pctx.AndroidRemoteStaticRule("cc", android.RemoteRuleSupports{Goma: true, RBE: true},
47		blueprint.RuleParams{
48			Depfile:     "${out}.d",
49			Deps:        blueprint.DepsGCC,
50			Command:     "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in$postCmd",
51			CommandDeps: []string{"$ccCmd"},
52		},
53		"ccCmd", "cFlags", "postCmd")
54
55	// Rule to invoke gcc with given command and flags, but no dependencies.
56	ccNoDeps = pctx.AndroidStaticRule("ccNoDeps",
57		blueprint.RuleParams{
58			Command:     "$relPwd $ccCmd -c $cFlags -o $out $in$postCmd",
59			CommandDeps: []string{"$ccCmd"},
60		},
61		"ccCmd", "cFlags", "postCmd")
62
63	// Rules to invoke ld to link binaries. Uses a .rsp file to list dependencies, as there may
64	// be many.
65	ld, ldRE = pctx.RemoteStaticRules("ld",
66		blueprint.RuleParams{
67			Command: "$reTemplate$ldCmd ${crtBegin} @${out}.rsp " +
68				"${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}",
69			CommandDeps:    []string{"$ldCmd"},
70			Rspfile:        "${out}.rsp",
71			RspfileContent: "${in} ${libFlags}",
72			// clang -Wl,--out-implib doesn't update its output file if it hasn't changed.
73			Restat: true,
74		},
75		&remoteexec.REParams{
76			Labels:          map[string]string{"type": "link", "tool": "clang"},
77			ExecStrategy:    "${config.RECXXLinksExecStrategy}",
78			Inputs:          []string{"${out}.rsp", "$implicitInputs"},
79			RSPFiles:        []string{"${out}.rsp"},
80			OutputFiles:     []string{"${out}", "$implicitOutputs"},
81			ToolchainInputs: []string{"$ldCmd"},
82			Platform:        map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
83		}, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitInputs", "implicitOutputs"})
84
85	// Rules for .o files to combine to other .o files, using ld partial linking.
86	partialLd, partialLdRE = pctx.RemoteStaticRules("partialLd",
87		blueprint.RuleParams{
88			// Without -no-pie, clang 7.0 adds -pie to link Android files,
89			// but -r and -pie cannot be used together.
90			Command:     "$reTemplate$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
91			CommandDeps: []string{"$ldCmd"},
92		}, &remoteexec.REParams{
93			Labels:          map[string]string{"type": "link", "tool": "clang"},
94			ExecStrategy:    "${config.RECXXLinksExecStrategy}",
95			Inputs:          []string{"$inCommaList", "$implicitInputs"},
96			OutputFiles:     []string{"${out}", "$implicitOutputs"},
97			ToolchainInputs: []string{"$ldCmd"},
98			Platform:        map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
99		}, []string{"ldCmd", "ldFlags"}, []string{"implicitInputs", "inCommaList", "implicitOutputs"})
100
101	// Rule to invoke `ar` with given cmd and flags, but no static library depenencies.
102	ar = pctx.AndroidStaticRule("ar",
103		blueprint.RuleParams{
104			Command:        "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
105			CommandDeps:    []string{"$arCmd"},
106			Rspfile:        "${out}.rsp",
107			RspfileContent: "${in}",
108		},
109		"arCmd", "arFlags")
110
111	// Rule to invoke `ar` with given cmd, flags, and library dependencies. Generates a .a
112	// (archive) file from .o files.
113	arWithLibs = pctx.AndroidStaticRule("arWithLibs",
114		blueprint.RuleParams{
115			Command:        "rm -f ${out} && $arCmd $arObjFlags $out @${out}.rsp && $arCmd $arLibFlags $out $arLibs",
116			CommandDeps:    []string{"$arCmd"},
117			Rspfile:        "${out}.rsp",
118			RspfileContent: "${arObjs}",
119		},
120		"arCmd", "arObjFlags", "arObjs", "arLibFlags", "arLibs")
121
122	// Rule to run objcopy --prefix-symbols (to prefix all symbols in a file with a given string).
123	prefixSymbols = pctx.AndroidStaticRule("prefixSymbols",
124		blueprint.RuleParams{
125			Command:     "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
126			CommandDeps: []string{"$objcopyCmd"},
127		},
128		"objcopyCmd", "prefix")
129
130	// Rule to run objcopy --remove-section=.llvm_addrsig on a partially linked object
131	noAddrSig = pctx.AndroidStaticRule("noAddrSig",
132		blueprint.RuleParams{
133			Command:     "rm -f ${out} && $objcopyCmd --remove-section=.llvm_addrsig ${in} ${out}",
134			CommandDeps: []string{"$objcopyCmd"},
135		},
136		"objcopyCmd")
137
138	_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
139	_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
140	_ = pctx.SourcePathVariable("createMiniDebugInfo", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/create_minidebuginfo")
141
142	// Rule to invoke `strip` (to discard symbols and data from object files).
143	strip = pctx.AndroidStaticRule("strip",
144		blueprint.RuleParams{
145			Depfile: "${out}.d",
146			Deps:    blueprint.DepsGCC,
147			Command: "XZ=$xzCmd CREATE_MINIDEBUGINFO=$createMiniDebugInfo CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
148			CommandDeps: func() []string {
149				if runtime.GOOS != "darwin" {
150					return []string{"$stripPath", "$xzCmd", "$createMiniDebugInfo"}
151				} else {
152					return []string{"$stripPath", "$xzCmd"}
153				}
154			}(),
155			Pool: darwinStripPool,
156		},
157		"args")
158
159	// Rule to invoke `strip` (to discard symbols and data from object files) on darwin architecture.
160	darwinStrip = func() blueprint.Rule {
161		if runtime.GOOS == "darwin" {
162			return pctx.AndroidStaticRule("darwinStrip",
163				blueprint.RuleParams{
164					Command:     "${config.MacStripPath} -u -r -o $out $in",
165					CommandDeps: []string{"${config.MacStripPath}"},
166				})
167		} else {
168			return nil
169		}
170	}()
171
172	// b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of
173	// file descriptors on darwin.  Limit concurrent calls to 5 on darwin.
174	darwinStripPool = func() blueprint.Pool {
175		if runtime.GOOS == "darwin" {
176			return pctx.StaticPool("darwinStripPool", blueprint.PoolParams{
177				Depth: 5,
178			})
179		} else {
180			return nil
181		}
182	}()
183
184	darwinLipo = func() blueprint.Rule {
185		if runtime.GOOS == "darwin" {
186			return pctx.AndroidStaticRule("darwinLipo",
187				blueprint.RuleParams{
188					Command:     "${config.MacLipoPath} -create -output $out $in",
189					CommandDeps: []string{"${config.MacLipoPath}"},
190				})
191		} else {
192			return nil
193		}
194	}()
195
196	_ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh")
197
198	// Rule to repack an archive (.a) file with a subset of object files.
199	archiveRepack = pctx.AndroidStaticRule("archiveRepack",
200		blueprint.RuleParams{
201			Depfile:     "${out}.d",
202			Deps:        blueprint.DepsGCC,
203			Command:     "CLANG_BIN=${config.ClangBin} $archiveRepackPath -i ${in} -o ${out} -d ${out}.d ${objects}",
204			CommandDeps: []string{"$archiveRepackPath"},
205		},
206		"objects")
207
208	// Rule to create an empty file at a given path.
209	emptyFile = pctx.AndroidStaticRule("emptyFile",
210		blueprint.RuleParams{
211			Command: "rm -f $out && touch $out",
212		})
213
214	_ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
215
216	// A rule for extracting a table of contents from a shared library (.so).
217	toc = pctx.AndroidStaticRule("toc",
218		blueprint.RuleParams{
219			Depfile:     "${out}.d",
220			Deps:        blueprint.DepsGCC,
221			Command:     "CLANG_BIN=$clangBin $tocPath $format -i ${in} -o ${out} -d ${out}.d",
222			CommandDeps: []string{"$tocPath"},
223			Restat:      true,
224		},
225		"clangBin", "format")
226
227	// Rules for invoking clang-tidy (a clang-based linter).
228	clangTidy, clangTidyRE = pctx.RemoteStaticRules("clangTidy",
229		blueprint.RuleParams{
230			Depfile: "${out}.d",
231			Deps:    blueprint.DepsGCC,
232			Command: "CLANG_CMD=$clangCmd TIDY_FILE=$out " +
233				"$tidyVars$reTemplate${config.ClangBin}/clang-tidy.sh $in $tidyFlags -- $cFlags",
234			CommandDeps: []string{"${config.ClangBin}/clang-tidy.sh", "$ccCmd", "$tidyCmd"},
235		},
236		&remoteexec.REParams{
237			Labels:               map[string]string{"type": "lint", "tool": "clang-tidy", "lang": "cpp"},
238			ExecStrategy:         "${config.REClangTidyExecStrategy}",
239			Inputs:               []string{"$in"},
240			OutputFiles:          []string{"${out}", "${out}.d"},
241			ToolchainInputs:      []string{"$ccCmd", "$tidyCmd"},
242			EnvironmentVariables: []string{"CLANG_CMD", "TIDY_FILE", "TIDY_TIMEOUT"},
243			// Although clang-tidy has an option to "fix" source files, that feature is hardly useable
244			// under parallel compilation and RBE. So we assume no OutputFiles here.
245			// The clang-tidy fix option is best run locally in single thread.
246			// Copying source file back to local caused two problems:
247			// (1) New timestamps trigger clang and clang-tidy compilations again.
248			// (2) Changing source files caused concurrent clang or clang-tidy jobs to crash.
249			Platform: map[string]string{remoteexec.PoolKey: "${config.REClangTidyPool}"},
250		}, []string{"cFlags", "ccCmd", "clangCmd", "tidyCmd", "tidyFlags", "tidyVars"}, []string{})
251
252	_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
253
254	// Rule for invoking yasm to compile .asm assembly files.
255	yasm = pctx.AndroidStaticRule("yasm",
256		blueprint.RuleParams{
257			Command:     "$yasmCmd $asFlags -o $out $in && $yasmCmd $asFlags -M $in >$out.d",
258			CommandDeps: []string{"$yasmCmd"},
259			Depfile:     "$out.d",
260			Deps:        blueprint.DepsGCC,
261		},
262		"asFlags")
263
264	_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
265
266	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
267	sAbiDump, sAbiDumpRE = pctx.RemoteStaticRules("sAbiDump",
268		blueprint.RuleParams{
269			Command:     "rm -f $out && $reTemplate$sAbiDumper --root-dir . --root-dir $$OUT_DIR:out -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
270			CommandDeps: []string{"$sAbiDumper"},
271		}, &remoteexec.REParams{
272			Labels:       map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"},
273			ExecStrategy: "${config.REAbiDumperExecStrategy}",
274			Inputs:       []string{"$sAbiLinkerLibs"},
275			Platform: map[string]string{
276				remoteexec.PoolKey: "${config.RECXXPool}",
277			},
278		}, []string{"cFlags", "exportDirs"}, nil)
279
280	_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
281	_ = pctx.SourcePathVariable("sAbiLinkerLibs", "prebuilts/clang-tools/${config.HostPrebuiltTag}/lib64")
282
283	// Rule to combine .dump sAbi dump files from multiple source files into a single .ldump
284	// sAbi dump file.
285	sAbiLink, sAbiLinkRE = pctx.RemoteStaticRules("sAbiLink",
286		blueprint.RuleParams{
287			Command:        "$reTemplate$sAbiLinker --root-dir . --root-dir $$OUT_DIR:out -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp",
288			CommandDeps:    []string{"$sAbiLinker"},
289			Rspfile:        "${out}.rsp",
290			RspfileContent: "${in}",
291		}, &remoteexec.REParams{
292			Labels:          map[string]string{"type": "tool", "name": "abi-linker"},
293			ExecStrategy:    "${config.REAbiLinkerExecStrategy}",
294			Inputs:          []string{"$sAbiLinkerLibs", "${out}.rsp", "$implicitInputs"},
295			RSPFiles:        []string{"${out}.rsp"},
296			OutputFiles:     []string{"$out"},
297			ToolchainInputs: []string{"$sAbiLinker"},
298			Platform:        map[string]string{remoteexec.PoolKey: "${config.RECXXPool}"},
299		}, []string{"symbolFilter", "arch", "exportedHeaderFlags"}, []string{"implicitInputs"})
300
301	_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
302
303	// Rule to compare linked sAbi dump files (.ldump).
304	sAbiDiff = pctx.RuleFunc("sAbiDiff",
305		func(ctx android.PackageRuleContext) blueprint.RuleParams {
306			commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
307			commandStr += "|| (echo '${errorMessage}'"
308			commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
309			commandStr += " && exit 1)"
310			return blueprint.RuleParams{
311				Command:     commandStr,
312				CommandDeps: []string{"$sAbiDiffer"},
313			}
314		},
315		"extraFlags", "referenceDump", "libName", "arch", "errorMessage")
316
317	// Rule to zip files.
318	zip = pctx.AndroidStaticRule("zip",
319		blueprint.RuleParams{
320			Command:        "${SoongZipCmd} -o ${out} -C $$OUT_DIR -r ${out}.rsp",
321			CommandDeps:    []string{"${SoongZipCmd}"},
322			Rspfile:        "${out}.rsp",
323			RspfileContent: "$in",
324		})
325
326	_ = pctx.SourcePathVariable("cxxExtractor",
327		"prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/cxx_extractor")
328	_ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
329	_ = pctx.VariableFunc("kytheCorpus",
330		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
331	_ = pctx.VariableFunc("kytheCuEncoding",
332		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
333
334	// Rule to use kythe extractors to generate .kzip files, used to build code cross references.
335	kytheExtract = pctx.StaticRule("kythe",
336		blueprint.RuleParams{
337			Command: `rm -f $out && ` +
338				`KYTHE_CORPUS=${kytheCorpus} ` +
339				`KYTHE_OUTPUT_FILE=$out ` +
340				`KYTHE_VNAMES=$kytheVnames ` +
341				`KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
342				`KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
343				`$cxxExtractor $cFlags $in `,
344			CommandDeps: []string{"$cxxExtractor", "$kytheVnames"},
345		},
346		"cFlags")
347
348	// Function pointer for producting staticlibs from rlibs. Corresponds to
349	// rust.TransformRlibstoStaticlib(), initialized in soong-rust (rust/builder.go init())
350	//
351	// This is required since soong-rust depends on soong-cc, so soong-cc cannot depend on soong-rust
352	// without resulting in a circular dependency. Setting this function pointer in soong-rust allows
353	// soong-cc to call into this particular function.
354	TransformRlibstoStaticlib (func(ctx android.ModuleContext, mainSrc android.Path, deps []RustRlibDep,
355		outputFile android.WritablePath) android.Path) = nil
356)
357
358func PwdPrefix() string {
359	// Darwin doesn't have /proc
360	if runtime.GOOS != "darwin" {
361		return "PWD=/proc/self/cwd"
362	}
363	return ""
364}
365
366func init() {
367	// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
368	// debug output. That way two builds in two different directories will
369	// create the same output.
370	pctx.StaticVariable("relPwd", PwdPrefix())
371
372	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
373}
374
375// builderFlags contains various types of command line flags (and settings) for use in building
376// build statements related to C++.
377type builderFlags struct {
378	// Global flags (which build system or toolchain is responsible for). These are separate from
379	// local flags because they should appear first (so that they may be overridden by local flags).
380	globalCommonFlags     string
381	globalAsFlags         string
382	globalYasmFlags       string
383	globalCFlags          string
384	globalToolingCFlags   string // A separate set of cFlags for clang LibTooling tools
385	globalToolingCppFlags string // A separate set of cppFlags for clang LibTooling tools
386	globalConlyFlags      string
387	globalCppFlags        string
388	globalLdFlags         string
389
390	// Local flags (which individual modules are responsible for). These may override global flags.
391	localCommonFlags     string
392	localAsFlags         string
393	localYasmFlags       string
394	localCFlags          string
395	localToolingCFlags   string // A separate set of cFlags for clang LibTooling tools
396	localToolingCppFlags string // A separate set of cppFlags for clang LibTooling tools
397	localConlyFlags      string
398	localCppFlags        string
399	localLdFlags         string
400
401	noOverrideFlags string // Flags appended at the end so they are not overridden.
402	libFlags        string // Flags to add to the linker directly after specifying libraries to link.
403	extraLibFlags   string // Flags to add to the linker last.
404	tidyFlags       string // Flags that apply to clang-tidy
405	sAbiFlags       string // Flags that apply to header-abi-dumps
406	aidlFlags       string // Flags that apply to aidl source files
407	rsFlags         string // Flags that apply to renderscript source files
408	toolchain       config.Toolchain
409
410	// True if these extra features are enabled.
411	tidy          bool
412	needTidyFiles bool
413	gcovCoverage  bool
414	sAbiDump      bool
415	emitXrefs     bool
416	clangVerify   bool
417
418	assemblerWithCpp bool // True if .s files should be processed with the c preprocessor.
419
420	systemIncludeFlags string
421
422	proto            android.ProtoFlags
423	protoC           bool // If true, compile protos as `.c` files. Otherwise, output as `.cc`.
424	protoOptionsFile bool // If true, output a proto options file.
425
426	yacc *YaccProperties
427	lex  *LexProperties
428}
429
430// StripFlags represents flags related to stripping. This is separate from builderFlags, as these
431// flags are useful outside of this package (such as for Rust).
432type StripFlags struct {
433	Toolchain                     config.Toolchain
434	StripKeepSymbols              bool
435	StripKeepSymbolsList          string
436	StripKeepSymbolsAndDebugFrame bool
437	StripKeepMiniDebugInfo        bool
438	StripAddGnuDebuglink          bool
439	StripUseGnuStrip              bool
440}
441
442// Objects is a collection of file paths corresponding to outputs for C++ related build statements.
443type Objects struct {
444	objFiles      android.Paths
445	tidyFiles     android.Paths
446	tidyDepFiles  android.Paths // link dependent .tidy files
447	coverageFiles android.Paths
448	sAbiDumpFiles android.Paths
449	kytheFiles    android.Paths
450}
451
452func (a Objects) Copy() Objects {
453	return Objects{
454		objFiles:      append(android.Paths{}, a.objFiles...),
455		tidyFiles:     append(android.Paths{}, a.tidyFiles...),
456		tidyDepFiles:  append(android.Paths{}, a.tidyDepFiles...),
457		coverageFiles: append(android.Paths{}, a.coverageFiles...),
458		sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
459		kytheFiles:    append(android.Paths{}, a.kytheFiles...),
460	}
461}
462
463func (a Objects) Append(b Objects) Objects {
464	return Objects{
465		objFiles:      append(a.objFiles, b.objFiles...),
466		tidyFiles:     append(a.tidyFiles, b.tidyFiles...),
467		tidyDepFiles:  append(a.tidyDepFiles, b.tidyDepFiles...),
468		coverageFiles: append(a.coverageFiles, b.coverageFiles...),
469		sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
470		kytheFiles:    append(a.kytheFiles, b.kytheFiles...),
471	}
472}
473
474// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
475func transformSourceToObj(ctx ModuleContext, subdir string, srcFiles, noTidySrcs, timeoutTidySrcs android.Paths,
476	flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
477	// Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
478	objFiles := make(android.Paths, len(srcFiles))
479	var tidyFiles android.Paths
480	noTidySrcsMap := make(map[string]bool)
481	var tidyVars string
482	if flags.tidy {
483		tidyFiles = make(android.Paths, 0, len(srcFiles))
484		for _, path := range noTidySrcs {
485			noTidySrcsMap[path.String()] = true
486		}
487		tidyTimeout := ctx.Config().Getenv("TIDY_TIMEOUT")
488		if len(tidyTimeout) > 0 {
489			tidyVars += "TIDY_TIMEOUT=" + tidyTimeout + " "
490			// add timeoutTidySrcs into noTidySrcsMap if TIDY_TIMEOUT is set
491			for _, path := range timeoutTidySrcs {
492				noTidySrcsMap[path.String()] = true
493			}
494		}
495	}
496	var coverageFiles android.Paths
497	if flags.gcovCoverage {
498		coverageFiles = make(android.Paths, 0, len(srcFiles))
499	}
500	var kytheFiles android.Paths
501	if flags.emitXrefs && ctx.Module() == ctx.PrimaryModule() {
502		kytheFiles = make(android.Paths, 0, len(srcFiles))
503	}
504
505	// Produce fully expanded flags for use by C tools, C compiles, C++ tools, C++ compiles, and asm compiles
506	// respectively.
507	toolingCflags := flags.globalCommonFlags + " " +
508		flags.globalToolingCFlags + " " +
509		flags.globalConlyFlags + " " +
510		flags.localCommonFlags + " " +
511		flags.localToolingCFlags + " " +
512		flags.localConlyFlags + " " +
513		flags.systemIncludeFlags + " " +
514		flags.noOverrideFlags
515
516	cflags := flags.globalCommonFlags + " " +
517		flags.globalCFlags + " " +
518		flags.globalConlyFlags + " " +
519		flags.localCommonFlags + " " +
520		flags.localCFlags + " " +
521		flags.localConlyFlags + " " +
522		flags.systemIncludeFlags + " " +
523		flags.noOverrideFlags
524
525	toolingCppflags := flags.globalCommonFlags + " " +
526		flags.globalToolingCFlags + " " +
527		flags.globalToolingCppFlags + " " +
528		flags.localCommonFlags + " " +
529		flags.localToolingCFlags + " " +
530		flags.localToolingCppFlags + " " +
531		flags.systemIncludeFlags + " " +
532		flags.noOverrideFlags
533
534	cppflags := flags.globalCommonFlags + " " +
535		flags.globalCFlags + " " +
536		flags.globalCppFlags + " " +
537		flags.localCommonFlags + " " +
538		flags.localCFlags + " " +
539		flags.localCppFlags + " " +
540		flags.systemIncludeFlags + " " +
541		flags.noOverrideFlags
542
543	asflags := flags.globalCommonFlags + " " +
544		flags.globalAsFlags + " " +
545		flags.localCommonFlags + " " +
546		flags.localAsFlags + " " +
547		flags.systemIncludeFlags
548
549	var sAbiDumpFiles android.Paths
550	if flags.sAbiDump {
551		sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
552	}
553
554	// Multiple source files have build rules usually share the same cFlags or tidyFlags.
555	// Define only one version in this module and share it in multiple build rules.
556	// To simplify the code, the shared variables are all named as $flags<nnn>.
557	shared := ctx.getSharedFlags()
558
559	// Share flags only when there are multiple files or tidy rules.
560	var hasMultipleRules = len(srcFiles) > 1 || flags.tidy
561
562	var shareFlags = func(kind string, flags string) string {
563		if !hasMultipleRules || len(flags) < 60 {
564			// Modules have long names and so do the module variables.
565			// It does not save space by replacing a short name with a long one.
566			return flags
567		}
568		mapKey := kind + flags
569		n, ok := shared.flagsMap[mapKey]
570		if !ok {
571			shared.numSharedFlags += 1
572			n = strconv.Itoa(shared.numSharedFlags)
573			shared.flagsMap[mapKey] = n
574			ctx.Variable(pctx, kind+n, flags)
575		}
576		return "$" + kind + n
577	}
578
579	for i, srcFile := range srcFiles {
580		objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
581
582		objFiles[i] = objFile
583
584		// Register compilation build statements. The actual rule used depends on the source file type.
585		switch srcFile.Ext() {
586		case ".asm":
587			ctx.Build(pctx, android.BuildParams{
588				Rule:        yasm,
589				Description: "yasm " + srcFile.Rel(),
590				Output:      objFile,
591				Input:       srcFile,
592				Implicits:   cFlagsDeps,
593				OrderOnly:   pathDeps,
594				Args: map[string]string{
595					"asFlags": shareFlags("asFlags", flags.globalYasmFlags+" "+flags.localYasmFlags),
596				},
597			})
598			continue
599		case ".o":
600			objFiles[i] = srcFile
601			continue
602		}
603
604		var moduleFlags string
605		var moduleToolingFlags string
606
607		var ccCmd string
608		var postCmd string
609		tidy := flags.tidy
610		coverage := flags.gcovCoverage
611		dump := flags.sAbiDump
612		rule := cc
613		emitXref := flags.emitXrefs
614
615		switch srcFile.Ext() {
616		case ".s":
617			if !flags.assemblerWithCpp {
618				rule = ccNoDeps
619			}
620			fallthrough
621		case ".S":
622			ccCmd = "clang"
623			moduleFlags = asflags
624			tidy = false
625			coverage = false
626			dump = false
627			emitXref = false
628		case ".c":
629			ccCmd = "clang"
630			moduleFlags = cflags
631			moduleToolingFlags = toolingCflags
632		case ".cpp", ".cc", ".cxx", ".mm":
633			ccCmd = "clang++"
634			moduleFlags = cppflags
635			moduleToolingFlags = toolingCppflags
636		case ".rs":
637			// A source provider (e.g. rust_bindgen) may provide both rs and c files.
638			// Ignore the rs files.
639			continue
640		case ".h", ".hpp":
641			ctx.PropertyErrorf("srcs", "Header file %s is not supported, instead use export_include_dirs or local_include_dirs.", srcFile)
642			continue
643		default:
644			ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .s, .S, .c, .cpp, .cc, .cxx, .mm", srcFile)
645			continue
646		}
647
648		// ccCmd is "clang" or "clang++"
649		ccDesc := ccCmd
650
651		ccCmd = "${config.ClangBin}/" + ccCmd
652
653		if flags.clangVerify {
654			postCmd = " && touch " + objFile.String()
655		}
656
657		var implicitOutputs android.WritablePaths
658		if coverage {
659			gcnoFile := android.ObjPathWithExt(ctx, subdir, srcFile, "gcno")
660			implicitOutputs = append(implicitOutputs, gcnoFile)
661			coverageFiles = append(coverageFiles, gcnoFile)
662		}
663
664		ctx.Build(pctx, android.BuildParams{
665			Rule:            rule,
666			Description:     ccDesc + " " + srcFile.Rel(),
667			Output:          objFile,
668			ImplicitOutputs: implicitOutputs,
669			Input:           srcFile,
670			Implicits:       cFlagsDeps,
671			OrderOnly:       pathDeps,
672			Args: map[string]string{
673				"cFlags":  shareFlags("cFlags", moduleFlags),
674				"ccCmd":   ccCmd, // short and not shared
675				"postCmd": postCmd,
676			},
677		})
678
679		// Register post-process build statements (such as for tidy or kythe).
680		if emitXref && ctx.Module() == ctx.PrimaryModule() {
681			kytheFile := android.ObjPathWithExt(ctx, subdir, srcFile, "kzip")
682			ctx.Build(pctx, android.BuildParams{
683				Rule:        kytheExtract,
684				Description: "Xref C++ extractor " + srcFile.Rel(),
685				Output:      kytheFile,
686				Input:       srcFile,
687				Implicits:   cFlagsDeps,
688				OrderOnly:   pathDeps,
689				Args: map[string]string{
690					"cFlags": shareFlags("cFlags", moduleFlags),
691				},
692			})
693			kytheFiles = append(kytheFiles, kytheFile)
694		}
695
696		//  Even with tidy, some src file could be skipped by noTidySrcsMap.
697		if tidy && !noTidySrcsMap[srcFile.String()] {
698			tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
699			tidyFiles = append(tidyFiles, tidyFile)
700			tidyCmd := "${config.ClangBin}/clang-tidy"
701
702			rule := clangTidy
703			if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CLANG_TIDY") {
704				rule = clangTidyRE
705			}
706
707			sharedCFlags := shareFlags("cFlags", moduleFlags)
708			srcRelPath := srcFile.Rel()
709
710			// Add the .tidy rule
711			ctx.Build(pctx, android.BuildParams{
712				Rule:        rule,
713				Description: "clang-tidy " + srcRelPath,
714				Output:      tidyFile,
715				Input:       srcFile,
716				Implicits:   cFlagsDeps,
717				OrderOnly:   pathDeps,
718				Args: map[string]string{
719					"cFlags":    sharedCFlags,
720					"ccCmd":     ccCmd,
721					"clangCmd":  ccDesc,
722					"tidyCmd":   tidyCmd,
723					"tidyFlags": shareFlags("tidyFlags", config.TidyFlagsForSrcFile(srcFile, flags.tidyFlags)),
724					"tidyVars":  tidyVars, // short and not shared
725				},
726			})
727		}
728
729		if dump {
730			sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
731			sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
732
733			dumpRule := sAbiDump
734			if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_DUMPER") {
735				dumpRule = sAbiDumpRE
736			}
737			ctx.Build(pctx, android.BuildParams{
738				Rule:        dumpRule,
739				Description: "header-abi-dumper " + srcFile.Rel(),
740				Output:      sAbiDumpFile,
741				Input:       srcFile,
742				Implicit:    objFile,
743				Implicits:   cFlagsDeps,
744				OrderOnly:   pathDeps,
745				Args: map[string]string{
746					"cFlags":     shareFlags("cFlags", moduleToolingFlags),
747					"exportDirs": shareFlags("exportDirs", flags.sAbiFlags),
748				},
749			})
750		}
751
752	}
753
754	var tidyDepFiles android.Paths
755	if flags.needTidyFiles {
756		tidyDepFiles = tidyFiles
757	}
758	return Objects{
759		objFiles:      objFiles,
760		tidyFiles:     tidyFiles,
761		tidyDepFiles:  tidyDepFiles,
762		coverageFiles: coverageFiles,
763		sAbiDumpFiles: sAbiDumpFiles,
764		kytheFiles:    kytheFiles,
765	}
766}
767
768// Generate a rule for compiling multiple .o files to a static library (.a)
769func transformObjToStaticLib(ctx android.ModuleContext,
770	objFiles android.Paths, wholeStaticLibs android.Paths,
771	flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.Paths) {
772
773	arCmd := "${config.ClangBin}/llvm-ar"
774	arFlags := ""
775	if !ctx.Darwin() {
776		arFlags += " --format=gnu"
777	}
778
779	if len(wholeStaticLibs) == 0 {
780		ctx.Build(pctx, android.BuildParams{
781			Rule:        ar,
782			Description: "static link " + outputFile.Base(),
783			Output:      outputFile,
784			Inputs:      objFiles,
785			Implicits:   deps,
786			Validations: validations,
787			Args: map[string]string{
788				"arFlags": "crsPD" + arFlags,
789				"arCmd":   arCmd,
790			},
791		})
792
793	} else {
794		ctx.Build(pctx, android.BuildParams{
795			Rule:        arWithLibs,
796			Description: "static link " + outputFile.Base(),
797			Output:      outputFile,
798			Inputs:      append(objFiles, wholeStaticLibs...),
799			Implicits:   deps,
800			Args: map[string]string{
801				"arCmd":      arCmd,
802				"arObjFlags": "crsPD" + arFlags,
803				"arObjs":     strings.Join(objFiles.Strings(), " "),
804				"arLibFlags": "cqsL" + arFlags,
805				"arLibs":     strings.Join(wholeStaticLibs.Strings(), " "),
806			},
807		})
808	}
809}
810
811// Generate a Rust staticlib from a list of rlibDeps. Returns nil if TransformRlibstoStaticlib is nil or rlibDeps is empty.
812func generateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
813	if TransformRlibstoStaticlib == nil && len(rlibDeps) > 0 {
814		// This should only be reachable if a module defines Rust deps in static_libs and
815		// soong-rust hasn't been loaded alongside soong-cc (e.g. in soong-cc tests).
816		panic(fmt.Errorf(
817			"TransformRlibstoStaticlib is not set and rust deps are defined in static_libs for %s",
818			ctx.ModuleName()))
819
820	} else if len(rlibDeps) == 0 {
821		return nil
822	}
823
824	output := android.PathForModuleOut(ctx, "generated_rust_staticlib", "librustlibs.a")
825	stemFile := output.ReplaceExtension(ctx, "rs")
826	crateNames := []string{}
827
828	// Collect crate names
829	for _, lib := range rlibDeps {
830		// Exclude libstd so this can support no_std builds.
831		if lib.CrateName != "libstd" {
832			crateNames = append(crateNames, lib.CrateName)
833		}
834	}
835
836	// Deduplicate any crateNames just to be safe
837	crateNames = android.FirstUniqueStrings(crateNames)
838
839	// Write the source file
840	android.WriteFileRule(ctx, stemFile, genRustStaticlibSrcFile(crateNames))
841
842	return TransformRlibstoStaticlib(ctx, stemFile, rlibDeps, output)
843}
844
845func genRustStaticlibSrcFile(crateNames []string) string {
846	lines := []string{
847		"// @Soong generated Source",
848		"#![no_std]", // pre-emptively set no_std to support both std and no_std.
849	}
850	for _, crate := range crateNames {
851		lines = append(lines, fmt.Sprintf("extern crate %s;", crate))
852	}
853	return strings.Join(lines, "\n")
854}
855
856// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
857// and shared libraries, to a shared library (.so) or dynamic executable
858func transformObjToDynamicBinary(ctx android.ModuleContext,
859	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps, crtBegin, crtEnd android.Paths,
860	groupLate bool, flags builderFlags, outputFile android.WritablePath,
861	implicitOutputs android.WritablePaths, validations android.Paths) {
862
863	ldCmd := "${config.ClangBin}/clang++"
864
865	var libFlagsList []string
866
867	if len(flags.libFlags) > 0 {
868		libFlagsList = append(libFlagsList, flags.libFlags)
869	}
870
871	if len(wholeStaticLibs) > 0 {
872		if ctx.Host() && ctx.Darwin() {
873			libFlagsList = append(libFlagsList, android.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
874		} else {
875			libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
876			libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
877			libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
878		}
879	}
880
881	libFlagsList = append(libFlagsList, staticLibs.Strings()...)
882
883	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
884		libFlagsList = append(libFlagsList, "-Wl,--start-group")
885	}
886	libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
887	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
888		libFlagsList = append(libFlagsList, "-Wl,--end-group")
889	}
890
891	for _, lib := range sharedLibs {
892		libFile := lib.String()
893		if ctx.Windows() {
894			libFile = pathtools.ReplaceExtension(libFile, "lib")
895		}
896		libFlagsList = append(libFlagsList, libFile)
897	}
898
899	deps = append(deps, staticLibs...)
900	deps = append(deps, lateStaticLibs...)
901	deps = append(deps, wholeStaticLibs...)
902	deps = append(deps, crtBegin...)
903	deps = append(deps, crtEnd...)
904
905	rule := ld
906	args := map[string]string{
907		"ldCmd":         ldCmd,
908		"crtBegin":      strings.Join(crtBegin.Strings(), " "),
909		"libFlags":      strings.Join(libFlagsList, " "),
910		"extraLibFlags": flags.extraLibFlags,
911		"ldFlags":       flags.globalLdFlags + " " + flags.localLdFlags,
912		"crtEnd":        strings.Join(crtEnd.Strings(), " "),
913	}
914
915	// On Windows, we always generate a PDB file
916	// --strip-debug is needed to also keep COFF symbols which are needed when
917	// we patch binaries with symbol_inject.
918	if ctx.Windows() {
919		pdb := outputFile.ReplaceExtension(ctx, "pdb")
920		args["ldFlags"] = args["ldFlags"] + " -Wl,--strip-debug -Wl,--pdb=" + pdb.String() + " "
921		implicitOutputs = append(slices.Clone(implicitOutputs), pdb)
922	}
923
924	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
925		rule = ldRE
926		args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",")
927		args["implicitInputs"] = strings.Join(deps.Strings(), ",")
928	}
929
930	ctx.Build(pctx, android.BuildParams{
931		Rule:            rule,
932		Description:     "link " + outputFile.Base(),
933		Output:          outputFile,
934		ImplicitOutputs: implicitOutputs,
935		Inputs:          objFiles,
936		Implicits:       deps,
937		OrderOnly:       sharedLibs,
938		Validations:     validations,
939		Args:            args,
940	})
941}
942
943// Generate a rule to combine .dump sAbi dump files from multiple source files
944// into a single .ldump sAbi dump file
945func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
946	baseName string, exportedIncludeDirs []string, symbolFile android.OptionalPath,
947	excludedSymbolVersions, excludedSymbolTags, includedSymbolTags []string,
948	api string) android.Path {
949
950	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
951
952	implicits := android.Paths{soFile}
953	symbolFilterStr := "-so " + soFile.String()
954	exportedHeaderFlags := android.JoinWithPrefix(exportedIncludeDirs, "-I")
955
956	if symbolFile.Valid() {
957		implicits = append(implicits, symbolFile.Path())
958		symbolFilterStr += " -v " + symbolFile.String()
959	}
960	for _, ver := range excludedSymbolVersions {
961		symbolFilterStr += " --exclude-symbol-version " + ver
962	}
963	for _, tag := range excludedSymbolTags {
964		symbolFilterStr += " --exclude-symbol-tag " + tag
965	}
966	for _, tag := range includedSymbolTags {
967		symbolFilterStr += " --include-symbol-tag " + tag
968	}
969	apiLevelsJson := android.GetApiLevelsJson(ctx)
970	implicits = append(implicits, apiLevelsJson)
971	symbolFilterStr += " --api-map " + apiLevelsJson.String()
972	symbolFilterStr += " --api " + api
973
974	rule := sAbiLink
975	args := map[string]string{
976		"symbolFilter":        symbolFilterStr,
977		"arch":                ctx.Arch().ArchType.Name,
978		"exportedHeaderFlags": exportedHeaderFlags,
979	}
980	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_LINKER") {
981		rule = sAbiLinkRE
982		rbeImplicits := append(implicits.Strings(), exportedIncludeDirs...)
983		args["implicitInputs"] = strings.Join(rbeImplicits, ",")
984	}
985	ctx.Build(pctx, android.BuildParams{
986		Rule:        rule,
987		Description: "header-abi-linker " + outputFile.Base(),
988		Output:      outputFile,
989		Inputs:      sAbiDumps,
990		Implicits:   implicits,
991		Args:        args,
992	})
993	return outputFile
994}
995
996func transformAbiDumpToAbiDiff(ctx android.ModuleContext, inputDump, referenceDump android.Path,
997	baseName, nameExt string, extraFlags []string, errorMessage string) android.Path {
998
999	var outputFile android.ModuleOutPath
1000	if nameExt != "" {
1001		outputFile = android.PathForModuleOut(ctx, baseName+"."+nameExt+".abidiff")
1002	} else {
1003		outputFile = android.PathForModuleOut(ctx, baseName+".abidiff")
1004	}
1005	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
1006
1007	ctx.Build(pctx, android.BuildParams{
1008		Rule:        sAbiDiff,
1009		Description: "header-abi-diff " + outputFile.Base(),
1010		Output:      outputFile,
1011		Input:       inputDump,
1012		Implicit:    referenceDump,
1013		Args: map[string]string{
1014			"referenceDump": referenceDump.String(),
1015			"libName":       libName,
1016			"arch":          ctx.Arch().ArchType.Name,
1017			"extraFlags":    strings.Join(extraFlags, " "),
1018			"errorMessage":  errorMessage,
1019		},
1020	})
1021	return outputFile
1022}
1023
1024// Generate a rule for extracting a table of contents from a shared library (.so)
1025func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) {
1026
1027	var format string
1028	if ctx.Darwin() {
1029		format = "--macho"
1030	} else if ctx.Windows() {
1031		format = "--pe"
1032	} else {
1033		format = "--elf"
1034	}
1035
1036	ctx.Build(pctx, android.BuildParams{
1037		Rule:        toc,
1038		Description: "generate toc " + inputFile.Base(),
1039		Output:      outputFile,
1040		Input:       inputFile,
1041		Args: map[string]string{
1042			"clangBin": "${config.ClangBin}",
1043			"format":   format,
1044		},
1045	})
1046}
1047
1048// Generate a rule for compiling multiple .o files to a .o using ld partial linking
1049func transformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
1050	flags builderFlags, outputFile android.WritablePath, deps android.Paths) {
1051
1052	ldCmd := "${config.ClangBin}/clang++"
1053
1054	rule := partialLd
1055	args := map[string]string{
1056		"ldCmd":   ldCmd,
1057		"ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
1058	}
1059	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
1060		rule = partialLdRE
1061		args["inCommaList"] = strings.Join(objFiles.Strings(), ",")
1062		args["implicitInputs"] = strings.Join(deps.Strings(), ",")
1063	}
1064	ctx.Build(pctx, android.BuildParams{
1065		Rule:        rule,
1066		Description: "link " + outputFile.Base(),
1067		Output:      outputFile,
1068		Inputs:      objFiles,
1069		Implicits:   deps,
1070		Args:        args,
1071	})
1072}
1073
1074// Generate a rule for running objcopy --prefix-symbols on a binary
1075func transformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path,
1076	flags builderFlags, outputFile android.WritablePath) {
1077
1078	objcopyCmd := "${config.ClangBin}/llvm-objcopy"
1079
1080	ctx.Build(pctx, android.BuildParams{
1081		Rule:        prefixSymbols,
1082		Description: "prefix symbols " + outputFile.Base(),
1083		Output:      outputFile,
1084		Input:       inputFile,
1085		Args: map[string]string{
1086			"objcopyCmd": objcopyCmd,
1087			"prefix":     prefix,
1088		},
1089	})
1090}
1091
1092// Generate a rule for running objcopy --remove-section=.llvm_addrsig on a partially linked object
1093func transformObjectNoAddrSig(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) {
1094	objcopyCmd := "${config.ClangBin}/llvm-objcopy"
1095
1096	ctx.Build(pctx, android.BuildParams{
1097		Rule:        noAddrSig,
1098		Description: "remove addrsig " + outputFile.Base(),
1099		Output:      outputFile,
1100		Input:       inputFile,
1101		Args: map[string]string{
1102			"objcopyCmd": objcopyCmd,
1103		},
1104	})
1105}
1106
1107// Registers a build statement to invoke `strip` (to discard symbols and data from object files).
1108func transformStrip(ctx android.ModuleContext, inputFile android.Path,
1109	outputFile android.WritablePath, flags StripFlags) {
1110
1111	args := ""
1112	if flags.StripAddGnuDebuglink {
1113		args += " --add-gnu-debuglink"
1114	}
1115	if flags.StripKeepMiniDebugInfo {
1116		args += " --keep-mini-debug-info"
1117	}
1118	if flags.StripKeepSymbols {
1119		args += " --keep-symbols"
1120	}
1121	if flags.StripKeepSymbolsList != "" {
1122		args += " -k" + flags.StripKeepSymbolsList
1123	}
1124	if flags.StripKeepSymbolsAndDebugFrame {
1125		args += " --keep-symbols-and-debug-frame"
1126	}
1127	if ctx.Windows() {
1128		args += " --windows"
1129	}
1130
1131	ctx.Build(pctx, android.BuildParams{
1132		Rule:        strip,
1133		Description: "strip " + outputFile.Base(),
1134		Output:      outputFile,
1135		Input:       inputFile,
1136		Args: map[string]string{
1137			"args": args,
1138		},
1139	})
1140}
1141
1142// Registers build statement to invoke `strip` on darwin architecture.
1143func transformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
1144	outputFile android.WritablePath) {
1145
1146	ctx.Build(pctx, android.BuildParams{
1147		Rule:        darwinStrip,
1148		Description: "strip " + outputFile.Base(),
1149		Output:      outputFile,
1150		Input:       inputFile,
1151	})
1152}
1153
1154func transformDarwinUniversalBinary(ctx android.ModuleContext, outputFile android.WritablePath, inputFiles ...android.Path) {
1155	ctx.Build(pctx, android.BuildParams{
1156		Rule:        darwinLipo,
1157		Description: "lipo " + outputFile.Base(),
1158		Output:      outputFile,
1159		Inputs:      inputFiles,
1160	})
1161}
1162
1163// Registers build statement to zip one or more coverage files.
1164func transformCoverageFilesToZip(ctx android.ModuleContext,
1165	inputs Objects, baseName string) android.OptionalPath {
1166
1167	if len(inputs.coverageFiles) > 0 {
1168		outputFile := android.PathForModuleOut(ctx, baseName+".zip")
1169
1170		ctx.Build(pctx, android.BuildParams{
1171			Rule:        zip,
1172			Description: "zip " + outputFile.Base(),
1173			Inputs:      inputs.coverageFiles,
1174			Output:      outputFile,
1175		})
1176
1177		return android.OptionalPathForPath(outputFile)
1178	}
1179
1180	return android.OptionalPath{}
1181}
1182
1183// Rule to repack an archive (.a) file with a subset of object files.
1184func transformArchiveRepack(ctx android.ModuleContext, inputFile android.Path,
1185	outputFile android.WritablePath, objects []string) {
1186
1187	ctx.Build(pctx, android.BuildParams{
1188		Rule:        archiveRepack,
1189		Description: "Repack archive " + outputFile.Base(),
1190		Output:      outputFile,
1191		Input:       inputFile,
1192		Args: map[string]string{
1193			"objects": strings.Join(objects, " "),
1194		},
1195	})
1196}
1197