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