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