Home | History | Annotate | Download | only in cc
      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 
     15 package 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 
     21 import (
     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 
     34 const (
     35 	objectExtension        = ".o"
     36 	staticLibraryExtension = ".a"
     37 )
     38 
     39 var (
     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 
    213 func 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 
    225 type 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 
    255 type Objects struct {
    256 	objFiles      android.Paths
    257 	tidyFiles     android.Paths
    258 	coverageFiles android.Paths
    259 	sAbiDumpFiles android.Paths
    260 }
    261 
    262 func (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 
    271 func (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
    281 func 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)
    447 func 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.
    477 func 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
    556 func 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
    627 func 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 
    651 func 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 
    661 func 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)
    679 func 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
    695 func 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
    717 func 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 
    733 func 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 
    759 func 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 
    769 func 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 
    783 func 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 
    797 func gccCmd(toolchain config.Toolchain, cmd string) string {
    798 	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
    799 }
    800 
    801 func 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