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