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