• 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	"fmt"
23	"path/filepath"
24	"runtime"
25	"strconv"
26	"strings"
27
28	"github.com/google/blueprint"
29
30	"android/soong/android"
31	"android/soong/cc/config"
32)
33
34const (
35	objectExtension        = ".o"
36	staticLibraryExtension = ".a"
37)
38
39var (
40	pctx = android.NewPackageContext("android/soong/cc")
41
42	cc = pctx.AndroidGomaStaticRule("cc",
43		blueprint.RuleParams{
44			Depfile:     "${out}.d",
45			Deps:        blueprint.DepsGCC,
46			Command:     "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
47			CommandDeps: []string{"$ccCmd"},
48			Description: "cc $out",
49		},
50		"ccCmd", "cFlags")
51
52	ld = pctx.AndroidStaticRule("ld",
53		blueprint.RuleParams{
54			Command: "$ldCmd ${crtBegin} @${out}.rsp " +
55				"${libFlags} ${crtEnd} -o ${out} ${ldFlags}",
56			CommandDeps:    []string{"$ldCmd"},
57			Description:    "ld $out",
58			Rspfile:        "${out}.rsp",
59			RspfileContent: "${in}",
60		},
61		"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags")
62
63	partialLd = pctx.AndroidStaticRule("partialLd",
64		blueprint.RuleParams{
65			Command:     "$ldCmd -nostdlib -Wl,-r ${in} -o ${out} ${ldFlags}",
66			CommandDeps: []string{"$ldCmd"},
67			Description: "partialLd $out",
68		},
69		"ldCmd", "ldFlags")
70
71	ar = pctx.AndroidStaticRule("ar",
72		blueprint.RuleParams{
73			Command:        "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
74			CommandDeps:    []string{"$arCmd"},
75			Description:    "ar $out",
76			Rspfile:        "${out}.rsp",
77			RspfileContent: "${in}",
78		},
79		"arCmd", "arFlags")
80
81	darwinAr = pctx.AndroidStaticRule("darwinAr",
82		blueprint.RuleParams{
83			Command:     "rm -f ${out} && ${config.MacArPath} $arFlags $out $in",
84			CommandDeps: []string{"${config.MacArPath}"},
85			Description: "ar $out",
86		},
87		"arFlags")
88
89	darwinAppendAr = pctx.AndroidStaticRule("darwinAppendAr",
90		blueprint.RuleParams{
91			Command:     "cp -f ${inAr} ${out}.tmp && ${config.MacArPath} $arFlags ${out}.tmp $in && mv ${out}.tmp ${out}",
92			CommandDeps: []string{"${config.MacArPath}", "${inAr}"},
93			Description: "ar $out",
94		},
95		"arFlags", "inAr")
96
97	darwinStrip = pctx.AndroidStaticRule("darwinStrip",
98		blueprint.RuleParams{
99			Command:     "${config.MacStripPath} -u -r -o $out $in",
100			CommandDeps: []string{"${config.MacStripPath}"},
101			Description: "strip $out",
102		})
103
104	prefixSymbols = pctx.AndroidStaticRule("prefixSymbols",
105		blueprint.RuleParams{
106			Command:     "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
107			CommandDeps: []string{"$objcopyCmd"},
108			Description: "prefixSymbols $out",
109		},
110		"objcopyCmd", "prefix")
111
112	_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
113
114	strip = pctx.AndroidStaticRule("strip",
115		blueprint.RuleParams{
116			Depfile:     "${out}.d",
117			Deps:        blueprint.DepsGCC,
118			Command:     "CROSS_COMPILE=$crossCompile $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
119			CommandDeps: []string{"$stripPath"},
120			Description: "strip $out",
121		},
122		"args", "crossCompile")
123
124	emptyFile = pctx.AndroidStaticRule("emptyFile",
125		blueprint.RuleParams{
126			Command:     "rm -f $out && touch $out",
127			Description: "empty file $out",
128		})
129
130	_ = pctx.SourcePathVariable("copyGccLibPath", "build/soong/scripts/copygcclib.sh")
131
132	copyGccLib = pctx.AndroidStaticRule("copyGccLib",
133		blueprint.RuleParams{
134			Depfile:     "${out}.d",
135			Deps:        blueprint.DepsGCC,
136			Command:     "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
137			CommandDeps: []string{"$copyGccLibPath", "$ccCmd"},
138			Description: "copy gcc $out",
139		},
140		"ccCmd", "cFlags", "libName")
141
142	_ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
143
144	toc = pctx.AndroidStaticRule("toc",
145		blueprint.RuleParams{
146			Depfile:     "${out}.d",
147			Deps:        blueprint.DepsGCC,
148			Command:     "CROSS_COMPILE=$crossCompile $tocPath -i ${in} -o ${out} -d ${out}.d",
149			CommandDeps: []string{"$tocPath"},
150			Restat:      true,
151		},
152		"crossCompile")
153
154	clangTidy = pctx.AndroidStaticRule("clangTidy",
155		blueprint.RuleParams{
156			Command:     "rm -f $out && ${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
157			CommandDeps: []string{"${config.ClangBin}/clang-tidy"},
158			Description: "tidy $out",
159		},
160		"cFlags", "tidyFlags")
161
162	_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
163
164	yasm = pctx.AndroidStaticRule("yasm",
165		blueprint.RuleParams{
166			Command:     "$yasmCmd $asFlags -o $out $in",
167			CommandDeps: []string{"$yasmCmd"},
168			Description: "yasm $out",
169		},
170		"asFlags")
171
172	_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
173
174	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
175	sAbiDump = pctx.AndroidStaticRule("sAbiDump",
176		blueprint.RuleParams{
177			Command:     "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem ${config.RSIncludePath}",
178			CommandDeps: []string{"$sAbiDumper"},
179			Description: "header-abi-dumper $in -o $out $exportDirs",
180		},
181		"cFlags", "exportDirs")
182
183	_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
184
185	sAbiLink = pctx.AndroidStaticRule("sAbiLink",
186		blueprint.RuleParams{
187			Command:        "$sAbiLinker -o ${out} $symbolFile -arch $arch -api $api $exportedHeaderFlags @${out}.rsp ",
188			CommandDeps:    []string{"$sAbiLinker"},
189			Description:    "header-abi-linker $in -o $out",
190			Rspfile:        "${out}.rsp",
191			RspfileContent: "${in}",
192		},
193		"symbolFile", "arch", "api", "exportedHeaderFlags")
194
195	_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
196
197	// Abidiff check turned on in advice-only mode. Builds will not fail on abi incompatibilties / extensions.
198	sAbiDiff = pctx.AndroidStaticRule("sAbiDiff",
199		blueprint.RuleParams{
200			Command:     "$sAbiDiffer -lib $libName -arch $arch -advice-only -o ${out} -new $in -old $referenceDump",
201			CommandDeps: []string{"$sAbiDiffer"},
202			Description: "header-abi-diff -o ${out} -new $in -old $referenceDump",
203		},
204		"referenceDump", "libName", "arch")
205
206	unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
207		blueprint.RuleParams{
208			Command:     "gunzip -c $in > $out",
209			Description: "gunzip $out",
210		})
211)
212
213func init() {
214	// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
215	// debug output. That way two builds in two different directories will
216	// create the same output.
217	if runtime.GOOS != "darwin" {
218		pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
219	} else {
220		// Darwin doesn't have /proc
221		pctx.StaticVariable("relPwd", "")
222	}
223}
224
225type builderFlags struct {
226	globalFlags string
227	arFlags     string
228	asFlags     string
229	cFlags      string
230	conlyFlags  string
231	cppFlags    string
232	ldFlags     string
233	libFlags    string
234	yaccFlags   string
235	protoFlags  string
236	tidyFlags   string
237	sAbiFlags   string
238	yasmFlags   string
239	aidlFlags   string
240	toolchain   config.Toolchain
241	clang       bool
242	tidy        bool
243	coverage    bool
244	sAbiDump    bool
245
246	systemIncludeFlags string
247
248	groupStaticLibs bool
249
250	stripKeepSymbols       bool
251	stripKeepMiniDebugInfo bool
252	stripAddGnuDebuglink   bool
253}
254
255type Objects struct {
256	objFiles      android.Paths
257	tidyFiles     android.Paths
258	coverageFiles android.Paths
259	sAbiDumpFiles android.Paths
260}
261
262func (a Objects) Copy() Objects {
263	return Objects{
264		objFiles:      append(android.Paths{}, a.objFiles...),
265		tidyFiles:     append(android.Paths{}, a.tidyFiles...),
266		coverageFiles: append(android.Paths{}, a.coverageFiles...),
267		sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
268	}
269}
270
271func (a Objects) Append(b Objects) Objects {
272	return Objects{
273		objFiles:      append(a.objFiles, b.objFiles...),
274		tidyFiles:     append(a.tidyFiles, b.tidyFiles...),
275		coverageFiles: append(a.coverageFiles, b.coverageFiles...),
276		sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
277	}
278}
279
280// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
281func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles android.Paths,
282	flags builderFlags, deps android.Paths) Objects {
283
284	objFiles := make(android.Paths, len(srcFiles))
285	var tidyFiles android.Paths
286	if flags.tidy && flags.clang {
287		tidyFiles = make(android.Paths, 0, len(srcFiles))
288	}
289	var coverageFiles android.Paths
290	if flags.coverage {
291		coverageFiles = make(android.Paths, 0, len(srcFiles))
292	}
293
294	cflags := strings.Join([]string{
295		flags.globalFlags,
296		flags.systemIncludeFlags,
297		flags.cFlags,
298		flags.conlyFlags,
299	}, " ")
300
301	cppflags := strings.Join([]string{
302		flags.globalFlags,
303		flags.systemIncludeFlags,
304		flags.cFlags,
305		flags.cppFlags,
306	}, " ")
307
308	asflags := strings.Join([]string{
309		flags.globalFlags,
310		flags.systemIncludeFlags,
311		flags.asFlags,
312	}, " ")
313	var sAbiDumpFiles android.Paths
314	if flags.sAbiDump && flags.clang {
315		sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
316	}
317
318	if flags.clang {
319		cflags += " ${config.NoOverrideClangGlobalCflags}"
320		cppflags += " ${config.NoOverrideClangGlobalCflags}"
321	} else {
322		cflags += " ${config.NoOverrideGlobalCflags}"
323		cppflags += " ${config.NoOverrideGlobalCflags}"
324	}
325
326	for i, srcFile := range srcFiles {
327		objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
328
329		objFiles[i] = objFile
330
331		if srcFile.Ext() == ".asm" {
332			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
333				Rule:      yasm,
334				Output:    objFile,
335				Input:     srcFile,
336				OrderOnly: deps,
337				Args: map[string]string{
338					"asFlags": flags.yasmFlags,
339				},
340			})
341			continue
342		}
343
344		var moduleCflags string
345		var ccCmd string
346		tidy := flags.tidy && flags.clang
347		coverage := flags.coverage
348		dump := flags.sAbiDump && flags.clang
349
350		switch srcFile.Ext() {
351		case ".S", ".s":
352			ccCmd = "gcc"
353			moduleCflags = asflags
354			tidy = false
355			coverage = false
356			dump = false
357		case ".c":
358			ccCmd = "gcc"
359			moduleCflags = cflags
360		case ".cpp", ".cc", ".mm":
361			ccCmd = "g++"
362			moduleCflags = cppflags
363		default:
364			ctx.ModuleErrorf("File %s has unknown extension", srcFile)
365			continue
366		}
367
368		if flags.clang {
369			switch ccCmd {
370			case "gcc":
371				ccCmd = "clang"
372			case "g++":
373				ccCmd = "clang++"
374			default:
375				panic("unrecoginzied ccCmd")
376			}
377
378			ccCmd = "${config.ClangBin}/" + ccCmd
379		} else {
380			ccCmd = gccCmd(flags.toolchain, ccCmd)
381		}
382
383		var implicitOutputs android.WritablePaths
384		if coverage {
385			gcnoFile := android.ObjPathWithExt(ctx, subdir, srcFile, "gcno")
386			implicitOutputs = append(implicitOutputs, gcnoFile)
387			coverageFiles = append(coverageFiles, gcnoFile)
388		}
389
390		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
391			Rule:            cc,
392			Output:          objFile,
393			ImplicitOutputs: implicitOutputs,
394			Input:           srcFile,
395			OrderOnly:       deps,
396			Args: map[string]string{
397				"cFlags": moduleCflags,
398				"ccCmd":  ccCmd,
399			},
400		})
401
402		if tidy {
403			tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
404			tidyFiles = append(tidyFiles, tidyFile)
405
406			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
407				Rule:   clangTidy,
408				Output: tidyFile,
409				Input:  srcFile,
410				// We must depend on objFile, since clang-tidy doesn't
411				// support exporting dependencies.
412				Implicit: objFile,
413				Args: map[string]string{
414					"cFlags":    moduleCflags,
415					"tidyFlags": flags.tidyFlags,
416				},
417			})
418		}
419
420		if dump {
421			sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
422			sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
423
424			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
425				Rule:     sAbiDump,
426				Output:   sAbiDumpFile,
427				Input:    srcFile,
428				Implicit: objFile,
429				Args: map[string]string{
430					"cFlags":     moduleCflags,
431					"exportDirs": flags.sAbiFlags,
432				},
433			})
434		}
435
436	}
437
438	return Objects{
439		objFiles:      objFiles,
440		tidyFiles:     tidyFiles,
441		coverageFiles: coverageFiles,
442		sAbiDumpFiles: sAbiDumpFiles,
443	}
444}
445
446// Generate a rule for compiling multiple .o files to a static library (.a)
447func TransformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths,
448	flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) {
449
450	if ctx.Darwin() {
451		transformDarwinObjToStaticLib(ctx, objFiles, flags, outputFile, deps)
452		return
453	}
454
455	arCmd := gccCmd(flags.toolchain, "ar")
456	arFlags := "crsPD"
457	if flags.arFlags != "" {
458		arFlags += " " + flags.arFlags
459	}
460
461	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
462		Rule:      ar,
463		Output:    outputFile,
464		Inputs:    objFiles,
465		Implicits: deps,
466		Args: map[string]string{
467			"arFlags": arFlags,
468			"arCmd":   arCmd,
469		},
470	})
471}
472
473// Generate a rule for compiling multiple .o files to a static library (.a) on
474// darwin.  The darwin ar tool doesn't support @file for list files, and has a
475// very small command line length limit, so we have to split the ar into multiple
476// steps, each appending to the previous one.
477func transformDarwinObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths,
478	flags builderFlags, outputPath android.ModuleOutPath, deps android.Paths) {
479
480	arFlags := "cqs"
481
482	if len(objFiles) == 0 {
483		dummy := android.PathForModuleOut(ctx, "dummy"+objectExtension)
484		dummyAr := android.PathForModuleOut(ctx, "dummy"+staticLibraryExtension)
485
486		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
487			Rule:      emptyFile,
488			Output:    dummy,
489			Implicits: deps,
490		})
491
492		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
493			Rule:   darwinAr,
494			Output: dummyAr,
495			Input:  dummy,
496			Args: map[string]string{
497				"arFlags": arFlags,
498			},
499		})
500
501		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
502			Rule:   darwinAppendAr,
503			Output: outputPath,
504			Input:  dummy,
505			Args: map[string]string{
506				"arFlags": "d",
507				"inAr":    dummyAr.String(),
508			},
509		})
510
511		return
512	}
513
514	// ARG_MAX on darwin is 262144, use half that to be safe
515	objFilesLists, err := splitListForSize(objFiles.Strings(), 131072)
516	if err != nil {
517		ctx.ModuleErrorf("%s", err.Error())
518	}
519
520	outputFile := outputPath.String()
521
522	var in, out string
523	for i, l := range objFilesLists {
524		in = out
525		out = outputFile
526		if i != len(objFilesLists)-1 {
527			out += "." + strconv.Itoa(i)
528		}
529
530		if in == "" {
531			ctx.Build(pctx, blueprint.BuildParams{
532				Rule:      darwinAr,
533				Outputs:   []string{out},
534				Inputs:    l,
535				Implicits: deps.Strings(),
536				Args: map[string]string{
537					"arFlags": arFlags,
538				},
539			})
540		} else {
541			ctx.Build(pctx, blueprint.BuildParams{
542				Rule:    darwinAppendAr,
543				Outputs: []string{out},
544				Inputs:  l,
545				Args: map[string]string{
546					"arFlags": arFlags,
547					"inAr":    in,
548				},
549			})
550		}
551	}
552}
553
554// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
555// and shared libraires, to a shared library (.so) or dynamic executable
556func TransformObjToDynamicBinary(ctx android.ModuleContext,
557	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
558	crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath) {
559
560	var ldCmd string
561	if flags.clang {
562		ldCmd = "${config.ClangBin}/clang++"
563	} else {
564		ldCmd = gccCmd(flags.toolchain, "g++")
565	}
566
567	var libFlagsList []string
568
569	if len(flags.libFlags) > 0 {
570		libFlagsList = append(libFlagsList, flags.libFlags)
571	}
572
573	if len(wholeStaticLibs) > 0 {
574		if ctx.Host() && ctx.Darwin() {
575			libFlagsList = append(libFlagsList, android.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
576		} else {
577			libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
578			libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
579			libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
580		}
581	}
582
583	if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 {
584		libFlagsList = append(libFlagsList, "-Wl,--start-group")
585	}
586	libFlagsList = append(libFlagsList, staticLibs.Strings()...)
587	if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 {
588		libFlagsList = append(libFlagsList, "-Wl,--end-group")
589	}
590
591	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
592		libFlagsList = append(libFlagsList, "-Wl,--start-group")
593	}
594	libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
595	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
596		libFlagsList = append(libFlagsList, "-Wl,--end-group")
597	}
598
599	for _, lib := range sharedLibs {
600		libFlagsList = append(libFlagsList, lib.String())
601	}
602
603	deps = append(deps, staticLibs...)
604	deps = append(deps, lateStaticLibs...)
605	deps = append(deps, wholeStaticLibs...)
606	if crtBegin.Valid() {
607		deps = append(deps, crtBegin.Path(), crtEnd.Path())
608	}
609
610	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
611		Rule:      ld,
612		Output:    outputFile,
613		Inputs:    objFiles,
614		Implicits: deps,
615		Args: map[string]string{
616			"ldCmd":    ldCmd,
617			"crtBegin": crtBegin.String(),
618			"libFlags": strings.Join(libFlagsList, " "),
619			"ldFlags":  flags.ldFlags,
620			"crtEnd":   crtEnd.String(),
621		},
622	})
623}
624
625// Generate a rule to combine .dump sAbi dump files from multiple source files
626// into a single .ldump sAbi dump file
627func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths,
628	symbolFile android.OptionalPath, apiLevel, baseName, exportedHeaderFlags string) android.OptionalPath {
629	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
630	var symbolFileStr string
631	var linkedDumpDep android.Path
632	if symbolFile.Valid() {
633		symbolFileStr = "-v " + symbolFile.Path().String()
634		linkedDumpDep = symbolFile.Path()
635	}
636	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
637		Rule:     sAbiLink,
638		Output:   outputFile,
639		Inputs:   sAbiDumps,
640		Implicit: linkedDumpDep,
641		Args: map[string]string{
642			"symbolFile": symbolFileStr,
643			"arch":       ctx.Arch().ArchType.Name,
644			"api":        apiLevel,
645			"exportedHeaderFlags": exportedHeaderFlags,
646		},
647	})
648	return android.OptionalPathForPath(outputFile)
649}
650
651func UnzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path {
652	outputFile := android.PathForModuleOut(ctx, baseName+"_ref.lsdump")
653	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
654		Rule:   unzipRefSAbiDump,
655		Output: outputFile,
656		Input:  zippedRefDump,
657	})
658	return outputFile
659}
660
661func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
662	baseName string) android.OptionalPath {
663	outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
664	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
665		Rule:     sAbiDiff,
666		Output:   outputFile,
667		Input:    inputDump,
668		Implicit: referenceDump,
669		Args: map[string]string{
670			"referenceDump": referenceDump.String(),
671			"libName":       baseName,
672			"arch":          ctx.Arch().ArchType.Name,
673		},
674	})
675	return android.OptionalPathForPath(outputFile)
676}
677
678// Generate a rule for extract a table of contents from a shared library (.so)
679func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.WritablePath,
680	outputFile android.WritablePath, flags builderFlags) {
681
682	crossCompile := gccCmd(flags.toolchain, "")
683
684	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
685		Rule:   toc,
686		Output: outputFile,
687		Input:  inputFile,
688		Args: map[string]string{
689			"crossCompile": crossCompile,
690		},
691	})
692}
693
694// Generate a rule for compiling multiple .o files to a .o using ld partial linking
695func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
696	flags builderFlags, outputFile android.WritablePath) {
697
698	var ldCmd string
699	if flags.clang {
700		ldCmd = "${config.ClangBin}/clang++"
701	} else {
702		ldCmd = gccCmd(flags.toolchain, "g++")
703	}
704
705	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
706		Rule:   partialLd,
707		Output: outputFile,
708		Inputs: objFiles,
709		Args: map[string]string{
710			"ldCmd":   ldCmd,
711			"ldFlags": flags.ldFlags,
712		},
713	})
714}
715
716// Generate a rule for runing objcopy --prefix-symbols on a binary
717func TransformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path,
718	flags builderFlags, outputFile android.WritablePath) {
719
720	objcopyCmd := gccCmd(flags.toolchain, "objcopy")
721
722	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
723		Rule:   prefixSymbols,
724		Output: outputFile,
725		Input:  inputFile,
726		Args: map[string]string{
727			"objcopyCmd": objcopyCmd,
728			"prefix":     prefix,
729		},
730	})
731}
732
733func TransformStrip(ctx android.ModuleContext, inputFile android.Path,
734	outputFile android.WritablePath, flags builderFlags) {
735
736	crossCompile := gccCmd(flags.toolchain, "")
737	args := ""
738	if flags.stripAddGnuDebuglink {
739		args += " --add-gnu-debuglink"
740	}
741	if flags.stripKeepMiniDebugInfo {
742		args += " --keep-mini-debug-info"
743	}
744	if flags.stripKeepSymbols {
745		args += " --keep-symbols"
746	}
747
748	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
749		Rule:   strip,
750		Output: outputFile,
751		Input:  inputFile,
752		Args: map[string]string{
753			"crossCompile": crossCompile,
754			"args":         args,
755		},
756	})
757}
758
759func TransformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
760	outputFile android.WritablePath) {
761
762	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
763		Rule:   darwinStrip,
764		Output: outputFile,
765		Input:  inputFile,
766	})
767}
768
769func TransformCoverageFilesToLib(ctx android.ModuleContext,
770	inputs Objects, flags builderFlags, baseName string) android.OptionalPath {
771
772	if len(inputs.coverageFiles) > 0 {
773		outputFile := android.PathForModuleOut(ctx, baseName+".gcnodir")
774
775		TransformObjToStaticLib(ctx, inputs.coverageFiles, flags, outputFile, nil)
776
777		return android.OptionalPathForPath(outputFile)
778	}
779
780	return android.OptionalPath{}
781}
782
783func CopyGccLib(ctx android.ModuleContext, libName string,
784	flags builderFlags, outputFile android.WritablePath) {
785
786	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
787		Rule:   copyGccLib,
788		Output: outputFile,
789		Args: map[string]string{
790			"ccCmd":   gccCmd(flags.toolchain, "gcc"),
791			"cFlags":  flags.globalFlags,
792			"libName": libName,
793		},
794	})
795}
796
797func gccCmd(toolchain config.Toolchain, cmd string) string {
798	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
799}
800
801func splitListForSize(list []string, limit int) (lists [][]string, err error) {
802	var i int
803
804	start := 0
805	bytes := 0
806	for i = range list {
807		l := len(list[i])
808		if l > limit {
809			return nil, fmt.Errorf("list element greater than size limit (%d)", limit)
810		}
811		if bytes+l > limit {
812			lists = append(lists, list[start:i])
813			start = i
814			bytes = 0
815		}
816		bytes += l + 1 // count a space between each list element
817	}
818
819	lists = append(lists, list[start:])
820
821	totalLen := 0
822	for _, l := range lists {
823		totalLen += len(l)
824	}
825	if totalLen != len(list) {
826		panic(fmt.Errorf("Failed breaking up list, %d != %d", len(list), totalLen))
827	}
828	return lists, nil
829}
830