• 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				"${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}",
67			CommandDeps:    []string{"$ldCmd"},
68			Rspfile:        "${out}.rsp",
69			RspfileContent: "${in} ${libFlags}",
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	// Rules for invoking clang-tidy (a clang-based linter).
206	clangTidy, clangTidyRE = pctx.RemoteStaticRules("clangTidy",
207		blueprint.RuleParams{
208			Depfile: "${out}.d",
209			Deps:    blueprint.DepsGCC,
210			Command: "CLANG_CMD=$clangCmd TIDY_FILE=$out " +
211				"$tidyVars$reTemplate${config.ClangBin}/clang-tidy.sh $in $tidyFlags -- $cFlags",
212			CommandDeps: []string{"${config.ClangBin}/clang-tidy.sh", "$ccCmd", "$tidyCmd"},
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			OutputFiles:          []string{"${out}", "${out}.d"},
219			ToolchainInputs:      []string{"$ccCmd", "$tidyCmd"},
220			EnvironmentVariables: []string{"CLANG_CMD", "TIDY_FILE", "TIDY_TIMEOUT"},
221			// Although clang-tidy has an option to "fix" source files, that feature is hardly useable
222			// under parallel compilation and RBE. So we assume no OutputFiles here.
223			// The clang-tidy fix option is best run locally in single thread.
224			// Copying source file back to local caused two problems:
225			// (1) New timestamps trigger clang and clang-tidy compilations again.
226			// (2) Changing source files caused concurrent clang or clang-tidy jobs to crash.
227			Platform: map[string]string{remoteexec.PoolKey: "${config.REClangTidyPool}"},
228		}, []string{"cFlags", "ccCmd", "clangCmd", "tidyCmd", "tidyFlags", "tidyVars"}, []string{})
229
230	_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
231
232	// Rule for invoking yasm to compile .asm assembly files.
233	yasm = pctx.AndroidStaticRule("yasm",
234		blueprint.RuleParams{
235			Command:     "$yasmCmd $asFlags -o $out $in && $yasmCmd $asFlags -M $in >$out.d",
236			CommandDeps: []string{"$yasmCmd"},
237			Depfile:     "$out.d",
238			Deps:        blueprint.DepsGCC,
239		},
240		"asFlags")
241
242	_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
243
244	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
245	sAbiDump, sAbiDumpRE = pctx.RemoteStaticRules("sAbiDump",
246		blueprint.RuleParams{
247			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",
248			CommandDeps: []string{"$sAbiDumper"},
249		}, &remoteexec.REParams{
250			Labels:       map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"},
251			ExecStrategy: "${config.REAbiDumperExecStrategy}",
252			Inputs:       []string{"$sAbiLinkerLibs"},
253			Platform: map[string]string{
254				remoteexec.PoolKey: "${config.RECXXPool}",
255			},
256		}, []string{"cFlags", "exportDirs"}, nil)
257
258	_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
259	_ = pctx.SourcePathVariable("sAbiLinkerLibs", "prebuilts/clang-tools/${config.HostPrebuiltTag}/lib64")
260
261	// Rule to combine .dump sAbi dump files from multiple source files into a single .ldump
262	// sAbi dump file.
263	sAbiLink, sAbiLinkRE = pctx.RemoteStaticRules("sAbiLink",
264		blueprint.RuleParams{
265			Command:        "$reTemplate$sAbiLinker --root-dir . --root-dir $$OUT_DIR:out -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp",
266			CommandDeps:    []string{"$sAbiLinker"},
267			Rspfile:        "${out}.rsp",
268			RspfileContent: "${in}",
269		}, &remoteexec.REParams{
270			Labels:          map[string]string{"type": "tool", "name": "abi-linker"},
271			ExecStrategy:    "${config.REAbiLinkerExecStrategy}",
272			Inputs:          []string{"$sAbiLinkerLibs", "${out}.rsp", "$implicitInputs"},
273			RSPFiles:        []string{"${out}.rsp"},
274			OutputFiles:     []string{"$out"},
275			ToolchainInputs: []string{"$sAbiLinker"},
276			Platform:        map[string]string{remoteexec.PoolKey: "${config.RECXXPool}"},
277		}, []string{"symbolFilter", "arch", "exportedHeaderFlags"}, []string{"implicitInputs"})
278
279	_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
280
281	// Rule to compare linked sAbi dump files (.ldump).
282	sAbiDiff = pctx.RuleFunc("sAbiDiff",
283		func(ctx android.PackageRuleContext) blueprint.RuleParams {
284			commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
285			commandStr += "|| (echo '${errorMessage}'"
286			commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
287			commandStr += " && exit 1)"
288			return blueprint.RuleParams{
289				Command:     commandStr,
290				CommandDeps: []string{"$sAbiDiffer"},
291			}
292		},
293		"extraFlags", "referenceDump", "libName", "arch", "errorMessage")
294
295	// Rule to zip files.
296	zip = pctx.AndroidStaticRule("zip",
297		blueprint.RuleParams{
298			Command:        "${SoongZipCmd} -o ${out} -C $$OUT_DIR -r ${out}.rsp",
299			CommandDeps:    []string{"${SoongZipCmd}"},
300			Rspfile:        "${out}.rsp",
301			RspfileContent: "$in",
302		})
303
304	_ = pctx.SourcePathVariable("cxxExtractor",
305		"prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/cxx_extractor")
306	_ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
307	_ = pctx.VariableFunc("kytheCorpus",
308		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
309	_ = pctx.VariableFunc("kytheCuEncoding",
310		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
311
312	// Rule to use kythe extractors to generate .kzip files, used to build code cross references.
313	kytheExtract = pctx.StaticRule("kythe",
314		blueprint.RuleParams{
315			Command: `rm -f $out && ` +
316				`KYTHE_CORPUS=${kytheCorpus} ` +
317				`KYTHE_OUTPUT_FILE=$out ` +
318				`KYTHE_VNAMES=$kytheVnames ` +
319				`KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
320				`KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
321				`$cxxExtractor $cFlags $in `,
322			CommandDeps: []string{"$cxxExtractor", "$kytheVnames"},
323		},
324		"cFlags")
325)
326
327func PwdPrefix() string {
328	// Darwin doesn't have /proc
329	if runtime.GOOS != "darwin" {
330		return "PWD=/proc/self/cwd"
331	}
332	return ""
333}
334
335func init() {
336	// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
337	// debug output. That way two builds in two different directories will
338	// create the same output.
339	pctx.StaticVariable("relPwd", PwdPrefix())
340
341	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
342}
343
344// builderFlags contains various types of command line flags (and settings) for use in building
345// build statements related to C++.
346type builderFlags struct {
347	// Global flags (which build system or toolchain is responsible for). These are separate from
348	// local flags because they should appear first (so that they may be overridden by local flags).
349	globalCommonFlags     string
350	globalAsFlags         string
351	globalYasmFlags       string
352	globalCFlags          string
353	globalToolingCFlags   string // A separate set of cFlags for clang LibTooling tools
354	globalToolingCppFlags string // A separate set of cppFlags for clang LibTooling tools
355	globalConlyFlags      string
356	globalCppFlags        string
357	globalLdFlags         string
358
359	// Local flags (which individual modules are responsible for). These may override global flags.
360	localCommonFlags     string
361	localAsFlags         string
362	localYasmFlags       string
363	localCFlags          string
364	localToolingCFlags   string // A separate set of cFlags for clang LibTooling tools
365	localToolingCppFlags string // A separate set of cppFlags for clang LibTooling tools
366	localConlyFlags      string
367	localCppFlags        string
368	localLdFlags         string
369
370	libFlags      string // Flags to add to the linker directly after specifying libraries to link.
371	extraLibFlags string // Flags to add to the linker last.
372	tidyFlags     string // Flags that apply to clang-tidy
373	sAbiFlags     string // Flags that apply to header-abi-dumps
374	aidlFlags     string // Flags that apply to aidl source files
375	rsFlags       string // Flags that apply to renderscript source files
376	toolchain     config.Toolchain
377
378	// True if these extra features are enabled.
379	tidy          bool
380	needTidyFiles bool
381	gcovCoverage  bool
382	sAbiDump      bool
383	emitXrefs     bool
384
385	assemblerWithCpp bool // True if .s files should be processed with the c preprocessor.
386
387	systemIncludeFlags string
388
389	proto            android.ProtoFlags
390	protoC           bool // If true, compile protos as `.c` files. Otherwise, output as `.cc`.
391	protoOptionsFile bool // If true, output a proto options file.
392
393	yacc *YaccProperties
394	lex  *LexProperties
395}
396
397// StripFlags represents flags related to stripping. This is separate from builderFlags, as these
398// flags are useful outside of this package (such as for Rust).
399type StripFlags struct {
400	Toolchain                     config.Toolchain
401	StripKeepSymbols              bool
402	StripKeepSymbolsList          string
403	StripKeepSymbolsAndDebugFrame bool
404	StripKeepMiniDebugInfo        bool
405	StripAddGnuDebuglink          bool
406	StripUseGnuStrip              bool
407}
408
409// Objects is a collection of file paths corresponding to outputs for C++ related build statements.
410type Objects struct {
411	objFiles      android.Paths
412	tidyFiles     android.Paths
413	tidyDepFiles  android.Paths // link dependent .tidy files
414	coverageFiles android.Paths
415	sAbiDumpFiles android.Paths
416	kytheFiles    android.Paths
417}
418
419func (a Objects) Copy() Objects {
420	return Objects{
421		objFiles:      append(android.Paths{}, a.objFiles...),
422		tidyFiles:     append(android.Paths{}, a.tidyFiles...),
423		tidyDepFiles:  append(android.Paths{}, a.tidyDepFiles...),
424		coverageFiles: append(android.Paths{}, a.coverageFiles...),
425		sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
426		kytheFiles:    append(android.Paths{}, a.kytheFiles...),
427	}
428}
429
430func (a Objects) Append(b Objects) Objects {
431	return Objects{
432		objFiles:      append(a.objFiles, b.objFiles...),
433		tidyFiles:     append(a.tidyFiles, b.tidyFiles...),
434		tidyDepFiles:  append(a.tidyDepFiles, b.tidyDepFiles...),
435		coverageFiles: append(a.coverageFiles, b.coverageFiles...),
436		sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
437		kytheFiles:    append(a.kytheFiles, b.kytheFiles...),
438	}
439}
440
441// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
442func transformSourceToObj(ctx ModuleContext, subdir string, srcFiles, noTidySrcs, timeoutTidySrcs android.Paths,
443	flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
444	// Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
445	objFiles := make(android.Paths, len(srcFiles))
446	var tidyFiles android.Paths
447	noTidySrcsMap := make(map[string]bool)
448	var tidyVars string
449	if flags.tidy {
450		tidyFiles = make(android.Paths, 0, len(srcFiles))
451		for _, path := range noTidySrcs {
452			noTidySrcsMap[path.String()] = true
453		}
454		tidyTimeout := ctx.Config().Getenv("TIDY_TIMEOUT")
455		if len(tidyTimeout) > 0 {
456			tidyVars += "TIDY_TIMEOUT=" + tidyTimeout + " "
457			// add timeoutTidySrcs into noTidySrcsMap if TIDY_TIMEOUT is set
458			for _, path := range timeoutTidySrcs {
459				noTidySrcsMap[path.String()] = true
460			}
461		}
462	}
463	var coverageFiles android.Paths
464	if flags.gcovCoverage {
465		coverageFiles = make(android.Paths, 0, len(srcFiles))
466	}
467	var kytheFiles android.Paths
468	if flags.emitXrefs {
469		kytheFiles = make(android.Paths, 0, len(srcFiles))
470	}
471
472	// Produce fully expanded flags for use by C tools, C compiles, C++ tools, C++ compiles, and asm compiles
473	// respectively.
474	toolingCflags := flags.globalCommonFlags + " " +
475		flags.globalToolingCFlags + " " +
476		flags.globalConlyFlags + " " +
477		flags.localCommonFlags + " " +
478		flags.localToolingCFlags + " " +
479		flags.localConlyFlags + " " +
480		flags.systemIncludeFlags
481
482	cflags := flags.globalCommonFlags + " " +
483		flags.globalCFlags + " " +
484		flags.globalConlyFlags + " " +
485		flags.localCommonFlags + " " +
486		flags.localCFlags + " " +
487		flags.localConlyFlags + " " +
488		flags.systemIncludeFlags
489
490	toolingCppflags := flags.globalCommonFlags + " " +
491		flags.globalToolingCFlags + " " +
492		flags.globalToolingCppFlags + " " +
493		flags.localCommonFlags + " " +
494		flags.localToolingCFlags + " " +
495		flags.localToolingCppFlags + " " +
496		flags.systemIncludeFlags
497
498	cppflags := flags.globalCommonFlags + " " +
499		flags.globalCFlags + " " +
500		flags.globalCppFlags + " " +
501		flags.localCommonFlags + " " +
502		flags.localCFlags + " " +
503		flags.localCppFlags + " " +
504		flags.systemIncludeFlags
505
506	asflags := flags.globalCommonFlags + " " +
507		flags.globalAsFlags + " " +
508		flags.localCommonFlags + " " +
509		flags.localAsFlags + " " +
510		flags.systemIncludeFlags
511
512	var sAbiDumpFiles android.Paths
513	if flags.sAbiDump {
514		sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
515	}
516
517	cflags += " ${config.NoOverrideGlobalCflags}"
518	toolingCflags += " ${config.NoOverrideGlobalCflags}"
519	cppflags += " ${config.NoOverrideGlobalCflags}"
520	toolingCppflags += " ${config.NoOverrideGlobalCflags}"
521
522	if flags.toolchain.Is64Bit() {
523		cflags += " ${config.NoOverride64GlobalCflags}"
524		toolingCflags += " ${config.NoOverride64GlobalCflags}"
525		cppflags += " ${config.NoOverride64GlobalCflags}"
526		toolingCppflags += " ${config.NoOverride64GlobalCflags}"
527	}
528
529	modulePath := android.PathForModuleSrc(ctx).String()
530	if android.IsThirdPartyPath(modulePath) {
531		cflags += " ${config.NoOverrideExternalGlobalCflags}"
532		toolingCflags += " ${config.NoOverrideExternalGlobalCflags}"
533		cppflags += " ${config.NoOverrideExternalGlobalCflags}"
534		toolingCppflags += " ${config.NoOverrideExternalGlobalCflags}"
535	}
536
537	// Multiple source files have build rules usually share the same cFlags or tidyFlags.
538	// Define only one version in this module and share it in multiple build rules.
539	// To simplify the code, the shared variables are all named as $flags<nnn>.
540	shared := ctx.getSharedFlags()
541
542	// Share flags only when there are multiple files or tidy rules.
543	var hasMultipleRules = len(srcFiles) > 1 || flags.tidy
544
545	var shareFlags = func(kind string, flags string) string {
546		if !hasMultipleRules || len(flags) < 60 {
547			// Modules have long names and so do the module variables.
548			// It does not save space by replacing a short name with a long one.
549			return flags
550		}
551		mapKey := kind + flags
552		n, ok := shared.flagsMap[mapKey]
553		if !ok {
554			shared.numSharedFlags += 1
555			n = strconv.Itoa(shared.numSharedFlags)
556			shared.flagsMap[mapKey] = n
557			ctx.Variable(pctx, kind+n, flags)
558		}
559		return "$" + kind + n
560	}
561
562	for i, srcFile := range srcFiles {
563		objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
564
565		objFiles[i] = objFile
566
567		// Register compilation build statements. The actual rule used depends on the source file type.
568		switch srcFile.Ext() {
569		case ".asm":
570			ctx.Build(pctx, android.BuildParams{
571				Rule:        yasm,
572				Description: "yasm " + srcFile.Rel(),
573				Output:      objFile,
574				Input:       srcFile,
575				Implicits:   cFlagsDeps,
576				OrderOnly:   pathDeps,
577				Args: map[string]string{
578					"asFlags": shareFlags("asFlags", flags.globalYasmFlags+" "+flags.localYasmFlags),
579				},
580			})
581			continue
582		case ".o":
583			objFiles[i] = srcFile
584			continue
585		}
586
587		var moduleFlags string
588		var moduleToolingFlags string
589
590		var ccCmd string
591		tidy := flags.tidy
592		coverage := flags.gcovCoverage
593		dump := flags.sAbiDump
594		rule := cc
595		emitXref := flags.emitXrefs
596
597		switch srcFile.Ext() {
598		case ".s":
599			if !flags.assemblerWithCpp {
600				rule = ccNoDeps
601			}
602			fallthrough
603		case ".S":
604			ccCmd = "clang"
605			moduleFlags = asflags
606			tidy = false
607			coverage = false
608			dump = false
609			emitXref = false
610		case ".c":
611			ccCmd = "clang"
612			moduleFlags = cflags
613			moduleToolingFlags = toolingCflags
614		case ".cpp", ".cc", ".cxx", ".mm":
615			ccCmd = "clang++"
616			moduleFlags = cppflags
617			moduleToolingFlags = toolingCppflags
618		case ".h", ".hpp":
619			ctx.PropertyErrorf("srcs", "Header file %s is not supported, instead use export_include_dirs or local_include_dirs.", srcFile)
620			continue
621		default:
622			ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .s, .S, .c, .cpp, .cc, .cxx, .mm", srcFile)
623			continue
624		}
625
626		// ccCmd is "clang" or "clang++"
627		ccDesc := ccCmd
628
629		ccCmd = "${config.ClangBin}/" + ccCmd
630
631		var implicitOutputs android.WritablePaths
632		if coverage {
633			gcnoFile := android.ObjPathWithExt(ctx, subdir, srcFile, "gcno")
634			implicitOutputs = append(implicitOutputs, gcnoFile)
635			coverageFiles = append(coverageFiles, gcnoFile)
636		}
637
638		ctx.Build(pctx, android.BuildParams{
639			Rule:            rule,
640			Description:     ccDesc + " " + srcFile.Rel(),
641			Output:          objFile,
642			ImplicitOutputs: implicitOutputs,
643			Input:           srcFile,
644			Implicits:       cFlagsDeps,
645			OrderOnly:       pathDeps,
646			Args: map[string]string{
647				"cFlags": shareFlags("cFlags", moduleFlags),
648				"ccCmd":  ccCmd, // short and not shared
649			},
650		})
651
652		// Register post-process build statements (such as for tidy or kythe).
653		if emitXref {
654			kytheFile := android.ObjPathWithExt(ctx, subdir, srcFile, "kzip")
655			ctx.Build(pctx, android.BuildParams{
656				Rule:        kytheExtract,
657				Description: "Xref C++ extractor " + srcFile.Rel(),
658				Output:      kytheFile,
659				Input:       srcFile,
660				Implicits:   cFlagsDeps,
661				OrderOnly:   pathDeps,
662				Args: map[string]string{
663					"cFlags": shareFlags("cFlags", moduleFlags),
664				},
665			})
666			kytheFiles = append(kytheFiles, kytheFile)
667		}
668
669		//  Even with tidy, some src file could be skipped by noTidySrcsMap.
670		if tidy && !noTidySrcsMap[srcFile.String()] {
671			tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
672			tidyFiles = append(tidyFiles, tidyFile)
673			tidyCmd := "${config.ClangBin}/clang-tidy"
674
675			rule := clangTidy
676			reducedCFlags := moduleFlags
677			if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CLANG_TIDY") {
678				rule = clangTidyRE
679				// b/248371171, work around RBE input processor problem
680				// some cflags rejected by input processor, but usually
681				// do not affect included files or clang-tidy
682				reducedCFlags = config.TidyReduceCFlags(reducedCFlags)
683			}
684
685			sharedCFlags := shareFlags("cFlags", reducedCFlags)
686			srcRelPath := srcFile.Rel()
687
688			// Add the .tidy rule
689			ctx.Build(pctx, android.BuildParams{
690				Rule:        rule,
691				Description: "clang-tidy " + srcRelPath,
692				Output:      tidyFile,
693				Input:       srcFile,
694				Implicits:   cFlagsDeps,
695				OrderOnly:   pathDeps,
696				Args: map[string]string{
697					"cFlags":    sharedCFlags,
698					"ccCmd":     ccCmd,
699					"clangCmd":  ccDesc,
700					"tidyCmd":   tidyCmd,
701					"tidyFlags": shareFlags("tidyFlags", config.TidyFlagsForSrcFile(srcFile, flags.tidyFlags)),
702					"tidyVars":  tidyVars, // short and not shared
703				},
704			})
705		}
706
707		if dump {
708			sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
709			sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
710
711			dumpRule := sAbiDump
712			if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_DUMPER") {
713				dumpRule = sAbiDumpRE
714			}
715			ctx.Build(pctx, android.BuildParams{
716				Rule:        dumpRule,
717				Description: "header-abi-dumper " + srcFile.Rel(),
718				Output:      sAbiDumpFile,
719				Input:       srcFile,
720				Implicit:    objFile,
721				Implicits:   cFlagsDeps,
722				OrderOnly:   pathDeps,
723				Args: map[string]string{
724					"cFlags":     shareFlags("cFlags", moduleToolingFlags),
725					"exportDirs": shareFlags("exportDirs", flags.sAbiFlags),
726				},
727			})
728		}
729
730	}
731
732	var tidyDepFiles android.Paths
733	if flags.needTidyFiles {
734		tidyDepFiles = tidyFiles
735	}
736	return Objects{
737		objFiles:      objFiles,
738		tidyFiles:     tidyFiles,
739		tidyDepFiles:  tidyDepFiles,
740		coverageFiles: coverageFiles,
741		sAbiDumpFiles: sAbiDumpFiles,
742		kytheFiles:    kytheFiles,
743	}
744}
745
746// Generate a rule for compiling multiple .o files to a static library (.a)
747func transformObjToStaticLib(ctx android.ModuleContext,
748	objFiles android.Paths, wholeStaticLibs android.Paths,
749	flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.Paths) {
750
751	arCmd := "${config.ClangBin}/llvm-ar"
752	arFlags := ""
753	if !ctx.Darwin() {
754		arFlags += " --format=gnu"
755	}
756
757	if len(wholeStaticLibs) == 0 {
758		ctx.Build(pctx, android.BuildParams{
759			Rule:        ar,
760			Description: "static link " + outputFile.Base(),
761			Output:      outputFile,
762			Inputs:      objFiles,
763			Implicits:   deps,
764			Validations: validations,
765			Args: map[string]string{
766				"arFlags": "crsPD" + arFlags,
767				"arCmd":   arCmd,
768			},
769		})
770
771	} else {
772		ctx.Build(pctx, android.BuildParams{
773			Rule:        arWithLibs,
774			Description: "static link " + outputFile.Base(),
775			Output:      outputFile,
776			Inputs:      append(objFiles, wholeStaticLibs...),
777			Implicits:   deps,
778			Args: map[string]string{
779				"arCmd":      arCmd,
780				"arObjFlags": "crsPD" + arFlags,
781				"arObjs":     strings.Join(objFiles.Strings(), " "),
782				"arLibFlags": "cqsL" + arFlags,
783				"arLibs":     strings.Join(wholeStaticLibs.Strings(), " "),
784			},
785		})
786	}
787}
788
789// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
790// and shared libraries, to a shared library (.so) or dynamic executable
791func transformObjToDynamicBinary(ctx android.ModuleContext,
792	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps, crtBegin, crtEnd android.Paths,
793	groupLate bool, flags builderFlags, outputFile android.WritablePath,
794	implicitOutputs android.WritablePaths, validations android.Paths) {
795
796	ldCmd := "${config.ClangBin}/clang++"
797
798	var libFlagsList []string
799
800	if len(flags.libFlags) > 0 {
801		libFlagsList = append(libFlagsList, flags.libFlags)
802	}
803
804	if len(wholeStaticLibs) > 0 {
805		if ctx.Host() && ctx.Darwin() {
806			libFlagsList = append(libFlagsList, android.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
807		} else {
808			libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
809			libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
810			libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
811		}
812	}
813
814	libFlagsList = append(libFlagsList, staticLibs.Strings()...)
815
816	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
817		libFlagsList = append(libFlagsList, "-Wl,--start-group")
818	}
819	libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
820	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
821		libFlagsList = append(libFlagsList, "-Wl,--end-group")
822	}
823
824	for _, lib := range sharedLibs {
825		libFile := lib.String()
826		if ctx.Windows() {
827			libFile = pathtools.ReplaceExtension(libFile, "lib")
828		}
829		libFlagsList = append(libFlagsList, libFile)
830	}
831
832	deps = append(deps, staticLibs...)
833	deps = append(deps, lateStaticLibs...)
834	deps = append(deps, wholeStaticLibs...)
835	deps = append(deps, crtBegin...)
836	deps = append(deps, crtEnd...)
837
838	rule := ld
839	args := map[string]string{
840		"ldCmd":         ldCmd,
841		"crtBegin":      strings.Join(crtBegin.Strings(), " "),
842		"libFlags":      strings.Join(libFlagsList, " "),
843		"extraLibFlags": flags.extraLibFlags,
844		"ldFlags":       flags.globalLdFlags + " " + flags.localLdFlags,
845		"crtEnd":        strings.Join(crtEnd.Strings(), " "),
846	}
847	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
848		rule = ldRE
849		args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",")
850		args["implicitInputs"] = strings.Join(deps.Strings(), ",")
851	}
852
853	ctx.Build(pctx, android.BuildParams{
854		Rule:            rule,
855		Description:     "link " + outputFile.Base(),
856		Output:          outputFile,
857		ImplicitOutputs: implicitOutputs,
858		Inputs:          objFiles,
859		Implicits:       deps,
860		OrderOnly:       sharedLibs,
861		Validations:     validations,
862		Args:            args,
863	})
864}
865
866// Generate a rule to combine .dump sAbi dump files from multiple source files
867// into a single .ldump sAbi dump file
868func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
869	baseName, exportedHeaderFlags string, symbolFile android.OptionalPath,
870	excludedSymbolVersions, excludedSymbolTags []string) android.OptionalPath {
871
872	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
873
874	implicits := android.Paths{soFile}
875	symbolFilterStr := "-so " + soFile.String()
876
877	if symbolFile.Valid() {
878		implicits = append(implicits, symbolFile.Path())
879		symbolFilterStr += " -v " + symbolFile.String()
880	}
881	for _, ver := range excludedSymbolVersions {
882		symbolFilterStr += " --exclude-symbol-version " + ver
883	}
884	for _, tag := range excludedSymbolTags {
885		symbolFilterStr += " --exclude-symbol-tag " + tag
886	}
887	rule := sAbiLink
888	args := map[string]string{
889		"symbolFilter":        symbolFilterStr,
890		"arch":                ctx.Arch().ArchType.Name,
891		"exportedHeaderFlags": exportedHeaderFlags,
892	}
893	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_LINKER") {
894		rule = sAbiLinkRE
895		rbeImplicits := implicits.Strings()
896		for _, p := range strings.Split(exportedHeaderFlags, " ") {
897			if len(p) > 2 {
898				// Exclude the -I prefix.
899				rbeImplicits = append(rbeImplicits, p[2:])
900			}
901		}
902		args["implicitInputs"] = strings.Join(rbeImplicits, ",")
903	}
904	ctx.Build(pctx, android.BuildParams{
905		Rule:        rule,
906		Description: "header-abi-linker " + outputFile.Base(),
907		Output:      outputFile,
908		Inputs:      sAbiDumps,
909		Implicits:   implicits,
910		Args:        args,
911	})
912	return android.OptionalPathForPath(outputFile)
913}
914
915func transformAbiDumpToAbiDiff(ctx android.ModuleContext, inputDump, referenceDump android.Path,
916	baseName, nameExt string, extraFlags []string, errorMessage string) android.Path {
917
918	var outputFile android.ModuleOutPath
919	if nameExt != "" {
920		outputFile = android.PathForModuleOut(ctx, baseName+"."+nameExt+".abidiff")
921	} else {
922		outputFile = android.PathForModuleOut(ctx, baseName+".abidiff")
923	}
924	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
925
926	ctx.Build(pctx, android.BuildParams{
927		Rule:        sAbiDiff,
928		Description: "header-abi-diff " + outputFile.Base(),
929		Output:      outputFile,
930		Input:       inputDump,
931		Implicit:    referenceDump,
932		Args: map[string]string{
933			"referenceDump": referenceDump.String(),
934			"libName":       libName,
935			"arch":          ctx.Arch().ArchType.Name,
936			"extraFlags":    strings.Join(extraFlags, " "),
937			"errorMessage":  errorMessage,
938		},
939	})
940	return outputFile
941}
942
943// Generate a rule for extracting a table of contents from a shared library (.so)
944func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) {
945
946	var format string
947	if ctx.Darwin() {
948		format = "--macho"
949	} else if ctx.Windows() {
950		format = "--pe"
951	} else {
952		format = "--elf"
953	}
954
955	ctx.Build(pctx, android.BuildParams{
956		Rule:        toc,
957		Description: "generate toc " + inputFile.Base(),
958		Output:      outputFile,
959		Input:       inputFile,
960		Args: map[string]string{
961			"clangBin": "${config.ClangBin}",
962			"format":   format,
963		},
964	})
965}
966
967// Generate a rule for compiling multiple .o files to a .o using ld partial linking
968func transformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
969	flags builderFlags, outputFile android.WritablePath, deps android.Paths) {
970
971	ldCmd := "${config.ClangBin}/clang++"
972
973	rule := partialLd
974	args := map[string]string{
975		"ldCmd":   ldCmd,
976		"ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
977	}
978	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
979		rule = partialLdRE
980		args["inCommaList"] = strings.Join(objFiles.Strings(), ",")
981		args["implicitInputs"] = strings.Join(deps.Strings(), ",")
982	}
983	ctx.Build(pctx, android.BuildParams{
984		Rule:        rule,
985		Description: "link " + outputFile.Base(),
986		Output:      outputFile,
987		Inputs:      objFiles,
988		Implicits:   deps,
989		Args:        args,
990	})
991}
992
993// Generate a rule for running objcopy --prefix-symbols on a binary
994func transformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path,
995	flags builderFlags, outputFile android.WritablePath) {
996
997	objcopyCmd := "${config.ClangBin}/llvm-objcopy"
998
999	ctx.Build(pctx, android.BuildParams{
1000		Rule:        prefixSymbols,
1001		Description: "prefix symbols " + outputFile.Base(),
1002		Output:      outputFile,
1003		Input:       inputFile,
1004		Args: map[string]string{
1005			"objcopyCmd": objcopyCmd,
1006			"prefix":     prefix,
1007		},
1008	})
1009}
1010
1011// Registers a build statement to invoke `strip` (to discard symbols and data from object files).
1012func transformStrip(ctx android.ModuleContext, inputFile android.Path,
1013	outputFile android.WritablePath, flags StripFlags) {
1014
1015	args := ""
1016	if flags.StripAddGnuDebuglink {
1017		args += " --add-gnu-debuglink"
1018	}
1019	if flags.StripKeepMiniDebugInfo {
1020		args += " --keep-mini-debug-info"
1021	}
1022	if flags.StripKeepSymbols {
1023		args += " --keep-symbols"
1024	}
1025	if flags.StripKeepSymbolsList != "" {
1026		args += " -k" + flags.StripKeepSymbolsList
1027	}
1028	if flags.StripKeepSymbolsAndDebugFrame {
1029		args += " --keep-symbols-and-debug-frame"
1030	}
1031
1032	ctx.Build(pctx, android.BuildParams{
1033		Rule:        strip,
1034		Description: "strip " + outputFile.Base(),
1035		Output:      outputFile,
1036		Input:       inputFile,
1037		Args: map[string]string{
1038			"args": args,
1039		},
1040	})
1041}
1042
1043// Registers build statement to invoke `strip` on darwin architecture.
1044func transformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
1045	outputFile android.WritablePath) {
1046
1047	ctx.Build(pctx, android.BuildParams{
1048		Rule:        darwinStrip,
1049		Description: "strip " + outputFile.Base(),
1050		Output:      outputFile,
1051		Input:       inputFile,
1052	})
1053}
1054
1055func transformDarwinUniversalBinary(ctx android.ModuleContext, outputFile android.WritablePath, inputFiles ...android.Path) {
1056	ctx.Build(pctx, android.BuildParams{
1057		Rule:        darwinLipo,
1058		Description: "lipo " + outputFile.Base(),
1059		Output:      outputFile,
1060		Inputs:      inputFiles,
1061	})
1062}
1063
1064// Registers build statement to zip one or more coverage files.
1065func transformCoverageFilesToZip(ctx android.ModuleContext,
1066	inputs Objects, baseName string) android.OptionalPath {
1067
1068	if len(inputs.coverageFiles) > 0 {
1069		outputFile := android.PathForModuleOut(ctx, baseName+".zip")
1070
1071		ctx.Build(pctx, android.BuildParams{
1072			Rule:        zip,
1073			Description: "zip " + outputFile.Base(),
1074			Inputs:      inputs.coverageFiles,
1075			Output:      outputFile,
1076		})
1077
1078		return android.OptionalPathForPath(outputFile)
1079	}
1080
1081	return android.OptionalPath{}
1082}
1083
1084// Rule to repack an archive (.a) file with a subset of object files.
1085func transformArchiveRepack(ctx android.ModuleContext, inputFile android.Path,
1086	outputFile android.WritablePath, objects []string) {
1087
1088	ctx.Build(pctx, android.BuildParams{
1089		Rule:        archiveRepack,
1090		Description: "Repack archive " + outputFile.Base(),
1091		Output:      outputFile,
1092		Input:       inputFile,
1093		Args: map[string]string{
1094			"objects": strings.Join(objects, " "),
1095		},
1096	})
1097}
1098