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