github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cc/builder.go (about) 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 }