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