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 "strings" 26 27 "github.com/google/blueprint" 28 "github.com/google/blueprint/pathtools" 29 30 "android/soong/android" 31 "android/soong/cc/config" 32 "android/soong/remoteexec" 33) 34 35const ( 36 objectExtension = ".o" 37 staticLibraryExtension = ".a" 38) 39 40var ( 41 pctx = android.NewPackageContext("android/soong/cc") 42 43 cc = pctx.AndroidRemoteStaticRule("cc", android.RemoteRuleSupports{Goma: true, RBE: true}, 44 blueprint.RuleParams{ 45 Depfile: "${out}.d", 46 Deps: blueprint.DepsGCC, 47 Command: "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in", 48 CommandDeps: []string{"$ccCmd"}, 49 }, 50 "ccCmd", "cFlags") 51 52 ccNoDeps = pctx.AndroidStaticRule("ccNoDeps", 53 blueprint.RuleParams{ 54 Command: "$relPwd $ccCmd -c $cFlags -o $out $in", 55 CommandDeps: []string{"$ccCmd"}, 56 }, 57 "ccCmd", "cFlags") 58 59 ld, ldRE = remoteexec.StaticRules(pctx, "ld", 60 blueprint.RuleParams{ 61 Command: "$reTemplate$ldCmd ${crtBegin} @${out}.rsp " + 62 "${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}", 63 CommandDeps: []string{"$ldCmd"}, 64 Rspfile: "${out}.rsp", 65 RspfileContent: "${in}", 66 // clang -Wl,--out-implib doesn't update its output file if it hasn't changed. 67 Restat: true, 68 }, 69 &remoteexec.REParams{ 70 Labels: map[string]string{"type": "link", "tool": "clang"}, 71 ExecStrategy: "${config.RECXXLinksExecStrategy}", 72 Inputs: []string{"${out}.rsp"}, 73 RSPFile: "${out}.rsp", 74 OutputFiles: []string{"${out}", "$implicitOutputs"}, 75 ToolchainInputs: []string{"$ldCmd"}, 76 Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"}, 77 }, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitOutputs"}) 78 79 partialLd, partialLdRE = remoteexec.StaticRules(pctx, "partialLd", 80 blueprint.RuleParams{ 81 // Without -no-pie, clang 7.0 adds -pie to link Android files, 82 // but -r and -pie cannot be used together. 83 Command: "$reTemplate$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}", 84 CommandDeps: []string{"$ldCmd"}, 85 }, &remoteexec.REParams{ 86 Labels: map[string]string{"type": "link", "tool": "clang"}, 87 ExecStrategy: "${config.RECXXLinksExecStrategy}", Inputs: []string{"$inCommaList"}, 88 OutputFiles: []string{"${out}", "$implicitOutputs"}, 89 ToolchainInputs: []string{"$ldCmd"}, 90 Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"}, 91 }, []string{"ldCmd", "ldFlags"}, []string{"inCommaList", "implicitOutputs"}) 92 93 ar = pctx.AndroidStaticRule("ar", 94 blueprint.RuleParams{ 95 Command: "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp", 96 CommandDeps: []string{"$arCmd"}, 97 Rspfile: "${out}.rsp", 98 RspfileContent: "${in}", 99 }, 100 "arCmd", "arFlags") 101 102 arWithLibs = pctx.AndroidStaticRule("arWithLibs", 103 blueprint.RuleParams{ 104 Command: "rm -f ${out} && $arCmd $arObjFlags $out @${out}.rsp && $arCmd $arLibFlags $out $arLibs", 105 CommandDeps: []string{"$arCmd"}, 106 Rspfile: "${out}.rsp", 107 RspfileContent: "${arObjs}", 108 }, 109 "arCmd", "arObjFlags", "arObjs", "arLibFlags", "arLibs") 110 111 darwinStrip = pctx.AndroidStaticRule("darwinStrip", 112 blueprint.RuleParams{ 113 Command: "${config.MacStripPath} -u -r -o $out $in", 114 CommandDeps: []string{"${config.MacStripPath}"}, 115 }) 116 117 prefixSymbols = pctx.AndroidStaticRule("prefixSymbols", 118 blueprint.RuleParams{ 119 Command: "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}", 120 CommandDeps: []string{"$objcopyCmd"}, 121 }, 122 "objcopyCmd", "prefix") 123 124 _ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh") 125 _ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz") 126 127 // b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of 128 // file descriptors on darwin. Limit concurrent calls to 5 on darwin. 129 darwinStripPool = func() blueprint.Pool { 130 if runtime.GOOS == "darwin" { 131 return pctx.StaticPool("darwinStripPool", blueprint.PoolParams{ 132 Depth: 5, 133 }) 134 } else { 135 return nil 136 } 137 }() 138 139 strip = pctx.AndroidStaticRule("strip", 140 blueprint.RuleParams{ 141 Depfile: "${out}.d", 142 Deps: blueprint.DepsGCC, 143 Command: "CROSS_COMPILE=$crossCompile XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d", 144 CommandDeps: []string{"$stripPath", "$xzCmd"}, 145 Pool: darwinStripPool, 146 }, 147 "args", "crossCompile") 148 149 _ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh") 150 151 archiveRepack = pctx.AndroidStaticRule("archiveRepack", 152 blueprint.RuleParams{ 153 Depfile: "${out}.d", 154 Deps: blueprint.DepsGCC, 155 Command: "CLANG_BIN=${config.ClangBin} $archiveRepackPath -i ${in} -o ${out} -d ${out}.d ${objects}", 156 CommandDeps: []string{"$archiveRepackPath"}, 157 }, 158 "objects") 159 160 emptyFile = pctx.AndroidStaticRule("emptyFile", 161 blueprint.RuleParams{ 162 Command: "rm -f $out && touch $out", 163 }) 164 165 _ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh") 166 167 toc = pctx.AndroidStaticRule("toc", 168 blueprint.RuleParams{ 169 Depfile: "${out}.d", 170 Deps: blueprint.DepsGCC, 171 Command: "CROSS_COMPILE=$crossCompile $tocPath $format -i ${in} -o ${out} -d ${out}.d", 172 CommandDeps: []string{"$tocPath"}, 173 Restat: true, 174 }, 175 "crossCompile", "format") 176 177 clangTidy = pctx.AndroidStaticRule("clangTidy", 178 blueprint.RuleParams{ 179 Command: "rm -f $out && ${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out", 180 CommandDeps: []string{"${config.ClangBin}/clang-tidy"}, 181 }, 182 "cFlags", "tidyFlags") 183 184 _ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm") 185 186 yasm = pctx.AndroidStaticRule("yasm", 187 blueprint.RuleParams{ 188 Command: "$yasmCmd $asFlags -o $out $in && $yasmCmd $asFlags -M $in >$out.d", 189 CommandDeps: []string{"$yasmCmd"}, 190 Depfile: "$out.d", 191 Deps: blueprint.DepsGCC, 192 }, 193 "asFlags") 194 195 windres = pctx.AndroidStaticRule("windres", 196 blueprint.RuleParams{ 197 Command: "$windresCmd $flags -I$$(dirname $in) -i $in -o $out --preprocessor \"${config.ClangBin}/clang -E -xc-header -DRC_INVOKED\"", 198 CommandDeps: []string{"$windresCmd"}, 199 }, 200 "windresCmd", "flags") 201 202 _ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper") 203 204 // -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information. 205 sAbiDump, sAbiDumpRE = remoteexec.StaticRules(pctx, "sAbiDump", 206 blueprint.RuleParams{ 207 Command: "rm -f $out && $reTemplate$sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers", 208 CommandDeps: []string{"$sAbiDumper"}, 209 }, &remoteexec.REParams{ 210 Labels: map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"}, 211 ExecStrategy: "${config.REAbiDumperExecStrategy}", 212 Platform: map[string]string{ 213 remoteexec.PoolKey: "${config.RECXXPool}", 214 "InputRootAbsolutePath": android.AbsSrcDirForExistingUseCases(), 215 }, 216 }, []string{"cFlags", "exportDirs"}, nil) 217 218 _ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker") 219 _ = pctx.SourcePathVariable("sAbiLinkerLibs", "prebuilts/clang-tools/${config.HostPrebuiltTag}/lib64") 220 221 sAbiLink, sAbiLinkRE = remoteexec.StaticRules(pctx, "sAbiLink", 222 blueprint.RuleParams{ 223 Command: "$reTemplate$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ", 224 CommandDeps: []string{"$sAbiLinker"}, 225 Rspfile: "${out}.rsp", 226 RspfileContent: "${in}", 227 }, &remoteexec.REParams{ 228 Labels: map[string]string{"type": "tool", "name": "abi-linker"}, 229 ExecStrategy: "${config.REAbiLinkerExecStrategy}", 230 Inputs: []string{"$sAbiLinkerLibs", "${out}.rsp", "$implicits"}, 231 RSPFile: "${out}.rsp", 232 OutputFiles: []string{"$out"}, 233 ToolchainInputs: []string{"$sAbiLinker"}, 234 Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXPool}"}, 235 }, []string{"symbolFilter", "arch", "exportedHeaderFlags"}, []string{"implicits"}) 236 237 _ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff") 238 239 sAbiDiff = pctx.RuleFunc("sAbiDiff", 240 func(ctx android.PackageRuleContext) blueprint.RuleParams { 241 commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})" 242 commandStr += "|| (echo 'error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py ${createReferenceDumpFlags} -l ${libName}'" 243 commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)" 244 commandStr += " && exit 1)" 245 return blueprint.RuleParams{ 246 Command: commandStr, 247 CommandDeps: []string{"$sAbiDiffer"}, 248 } 249 }, 250 "extraFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags") 251 252 unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump", 253 blueprint.RuleParams{ 254 Command: "gunzip -c $in > $out", 255 }) 256 257 zip = pctx.AndroidStaticRule("zip", 258 blueprint.RuleParams{ 259 Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp", 260 CommandDeps: []string{"${SoongZipCmd}"}, 261 Rspfile: "$out.rsp", 262 RspfileContent: "$in", 263 }) 264 265 _ = pctx.SourcePathVariable("cxxExtractor", 266 "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/cxx_extractor") 267 _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json") 268 _ = pctx.VariableFunc("kytheCorpus", 269 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() }) 270 _ = pctx.VariableFunc("kytheCuEncoding", 271 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() }) 272 kytheExtract = pctx.StaticRule("kythe", 273 blueprint.RuleParams{ 274 Command: `rm -f $out && ` + 275 `KYTHE_CORPUS=${kytheCorpus} ` + 276 `KYTHE_OUTPUT_FILE=$out ` + 277 `KYTHE_VNAMES=$kytheVnames ` + 278 `KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` + 279 `KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` + 280 `$cxxExtractor $cFlags $in `, 281 CommandDeps: []string{"$cxxExtractor", "$kytheVnames"}, 282 }, 283 "cFlags") 284) 285 286func PwdPrefix() string { 287 // Darwin doesn't have /proc 288 if runtime.GOOS != "darwin" { 289 return "PWD=/proc/self/cwd" 290 } 291 return "" 292} 293 294func init() { 295 // We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the 296 // debug output. That way two builds in two different directories will 297 // create the same output. 298 pctx.StaticVariable("relPwd", PwdPrefix()) 299 300 pctx.HostBinToolVariable("SoongZipCmd", "soong_zip") 301 pctx.Import("android/soong/remoteexec") 302} 303 304type builderFlags struct { 305 globalCommonFlags string 306 globalAsFlags string 307 globalYasmFlags string 308 globalCFlags string 309 globalToolingCFlags string // A separate set of cFlags for clang LibTooling tools 310 globalToolingCppFlags string // A separate set of cppFlags for clang LibTooling tools 311 globalConlyFlags string 312 globalCppFlags string 313 globalLdFlags string 314 315 localCommonFlags string 316 localAsFlags string 317 localYasmFlags string 318 localCFlags string 319 localToolingCFlags string // A separate set of cFlags for clang LibTooling tools 320 localToolingCppFlags string // A separate set of cppFlags for clang LibTooling tools 321 localConlyFlags string 322 localCppFlags string 323 localLdFlags string 324 325 libFlags string 326 extraLibFlags string 327 tidyFlags string 328 sAbiFlags string 329 aidlFlags string 330 rsFlags string 331 toolchain config.Toolchain 332 tidy bool 333 gcovCoverage bool 334 sAbiDump bool 335 emitXrefs bool 336 337 assemblerWithCpp bool 338 339 systemIncludeFlags string 340 341 groupStaticLibs bool 342 343 stripKeepSymbols bool 344 stripKeepSymbolsList string 345 stripKeepSymbolsAndDebugFrame bool 346 stripKeepMiniDebugInfo bool 347 stripAddGnuDebuglink bool 348 stripUseGnuStrip bool 349 350 proto android.ProtoFlags 351 protoC bool 352 protoOptionsFile bool 353 354 yacc *YaccProperties 355} 356 357type Objects struct { 358 objFiles android.Paths 359 tidyFiles android.Paths 360 coverageFiles android.Paths 361 sAbiDumpFiles android.Paths 362 kytheFiles android.Paths 363} 364 365func (a Objects) Copy() Objects { 366 return Objects{ 367 objFiles: append(android.Paths{}, a.objFiles...), 368 tidyFiles: append(android.Paths{}, a.tidyFiles...), 369 coverageFiles: append(android.Paths{}, a.coverageFiles...), 370 sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...), 371 kytheFiles: append(android.Paths{}, a.kytheFiles...), 372 } 373} 374 375func (a Objects) Append(b Objects) Objects { 376 return Objects{ 377 objFiles: append(a.objFiles, b.objFiles...), 378 tidyFiles: append(a.tidyFiles, b.tidyFiles...), 379 coverageFiles: append(a.coverageFiles, b.coverageFiles...), 380 sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...), 381 kytheFiles: append(a.kytheFiles, b.kytheFiles...), 382 } 383} 384 385// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files 386func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles android.Paths, 387 flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects { 388 389 objFiles := make(android.Paths, len(srcFiles)) 390 var tidyFiles android.Paths 391 if flags.tidy { 392 tidyFiles = make(android.Paths, 0, len(srcFiles)) 393 } 394 var coverageFiles android.Paths 395 if flags.gcovCoverage { 396 coverageFiles = make(android.Paths, 0, len(srcFiles)) 397 } 398 var kytheFiles android.Paths 399 if flags.emitXrefs { 400 kytheFiles = make(android.Paths, 0, len(srcFiles)) 401 } 402 403 // Produce fully expanded flags for use by C tools, C compiles, C++ tools, C++ compiles, and asm compiles 404 // respectively. 405 toolingCflags := flags.globalCommonFlags + " " + 406 flags.globalToolingCFlags + " " + 407 flags.globalConlyFlags + " " + 408 flags.localCommonFlags + " " + 409 flags.localToolingCFlags + " " + 410 flags.localConlyFlags + " " + 411 flags.systemIncludeFlags 412 413 cflags := flags.globalCommonFlags + " " + 414 flags.globalCFlags + " " + 415 flags.globalConlyFlags + " " + 416 flags.localCommonFlags + " " + 417 flags.localCFlags + " " + 418 flags.localConlyFlags + " " + 419 flags.systemIncludeFlags 420 421 toolingCppflags := flags.globalCommonFlags + " " + 422 flags.globalToolingCFlags + " " + 423 flags.globalToolingCppFlags + " " + 424 flags.localCommonFlags + " " + 425 flags.localToolingCFlags + " " + 426 flags.localToolingCppFlags + " " + 427 flags.systemIncludeFlags 428 429 cppflags := flags.globalCommonFlags + " " + 430 flags.globalCFlags + " " + 431 flags.globalCppFlags + " " + 432 flags.localCommonFlags + " " + 433 flags.localCFlags + " " + 434 flags.localCppFlags + " " + 435 flags.systemIncludeFlags 436 437 asflags := flags.globalCommonFlags + " " + 438 flags.globalAsFlags + " " + 439 flags.localCommonFlags + " " + 440 flags.localAsFlags + " " + 441 flags.systemIncludeFlags 442 443 var sAbiDumpFiles android.Paths 444 if flags.sAbiDump { 445 sAbiDumpFiles = make(android.Paths, 0, len(srcFiles)) 446 } 447 448 cflags += " ${config.NoOverrideClangGlobalCflags}" 449 toolingCflags += " ${config.NoOverrideClangGlobalCflags}" 450 cppflags += " ${config.NoOverrideClangGlobalCflags}" 451 toolingCppflags += " ${config.NoOverrideClangGlobalCflags}" 452 453 for i, srcFile := range srcFiles { 454 objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o") 455 456 objFiles[i] = objFile 457 458 switch srcFile.Ext() { 459 case ".asm": 460 ctx.Build(pctx, android.BuildParams{ 461 Rule: yasm, 462 Description: "yasm " + srcFile.Rel(), 463 Output: objFile, 464 Input: srcFile, 465 Implicits: cFlagsDeps, 466 OrderOnly: pathDeps, 467 Args: map[string]string{ 468 "asFlags": flags.globalYasmFlags + " " + flags.localYasmFlags, 469 }, 470 }) 471 continue 472 case ".rc": 473 ctx.Build(pctx, android.BuildParams{ 474 Rule: windres, 475 Description: "windres " + srcFile.Rel(), 476 Output: objFile, 477 Input: srcFile, 478 Implicits: cFlagsDeps, 479 OrderOnly: pathDeps, 480 Args: map[string]string{ 481 "windresCmd": gccCmd(flags.toolchain, "windres"), 482 "flags": flags.toolchain.WindresFlags(), 483 }, 484 }) 485 continue 486 case ".o": 487 objFiles[i] = srcFile 488 continue 489 } 490 491 var moduleFlags string 492 var moduleToolingFlags string 493 494 var ccCmd string 495 tidy := flags.tidy 496 coverage := flags.gcovCoverage 497 dump := flags.sAbiDump 498 rule := cc 499 emitXref := flags.emitXrefs 500 501 switch srcFile.Ext() { 502 case ".s": 503 if !flags.assemblerWithCpp { 504 rule = ccNoDeps 505 } 506 fallthrough 507 case ".S": 508 ccCmd = "clang" 509 moduleFlags = asflags 510 tidy = false 511 coverage = false 512 dump = false 513 emitXref = false 514 case ".c": 515 ccCmd = "clang" 516 moduleFlags = cflags 517 moduleToolingFlags = toolingCflags 518 case ".cpp", ".cc", ".cxx", ".mm": 519 ccCmd = "clang++" 520 moduleFlags = cppflags 521 moduleToolingFlags = toolingCppflags 522 default: 523 ctx.ModuleErrorf("File %s has unknown extension", srcFile) 524 continue 525 } 526 527 ccDesc := ccCmd 528 529 ccCmd = "${config.ClangBin}/" + ccCmd 530 531 var implicitOutputs android.WritablePaths 532 if coverage { 533 gcnoFile := android.ObjPathWithExt(ctx, subdir, srcFile, "gcno") 534 implicitOutputs = append(implicitOutputs, gcnoFile) 535 coverageFiles = append(coverageFiles, gcnoFile) 536 } 537 538 ctx.Build(pctx, android.BuildParams{ 539 Rule: rule, 540 Description: ccDesc + " " + srcFile.Rel(), 541 Output: objFile, 542 ImplicitOutputs: implicitOutputs, 543 Input: srcFile, 544 Implicits: cFlagsDeps, 545 OrderOnly: pathDeps, 546 Args: map[string]string{ 547 "cFlags": moduleFlags, 548 "ccCmd": ccCmd, 549 }, 550 }) 551 552 if emitXref { 553 kytheFile := android.ObjPathWithExt(ctx, subdir, srcFile, "kzip") 554 ctx.Build(pctx, android.BuildParams{ 555 Rule: kytheExtract, 556 Description: "Xref C++ extractor " + srcFile.Rel(), 557 Output: kytheFile, 558 Input: srcFile, 559 Implicits: cFlagsDeps, 560 OrderOnly: pathDeps, 561 Args: map[string]string{ 562 "cFlags": moduleFlags, 563 }, 564 }) 565 kytheFiles = append(kytheFiles, kytheFile) 566 } 567 568 if tidy { 569 tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy") 570 tidyFiles = append(tidyFiles, tidyFile) 571 572 ctx.Build(pctx, android.BuildParams{ 573 Rule: clangTidy, 574 Description: "clang-tidy " + srcFile.Rel(), 575 Output: tidyFile, 576 Input: srcFile, 577 // We must depend on objFile, since clang-tidy doesn't 578 // support exporting dependencies. 579 Implicit: objFile, 580 Implicits: cFlagsDeps, 581 OrderOnly: pathDeps, 582 Args: map[string]string{ 583 "cFlags": moduleToolingFlags, 584 "tidyFlags": flags.tidyFlags, 585 }, 586 }) 587 } 588 589 if dump { 590 sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump") 591 sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile) 592 593 dumpRule := sAbiDump 594 if ctx.Config().IsEnvTrue("RBE_ABI_DUMPER") { 595 dumpRule = sAbiDumpRE 596 } 597 ctx.Build(pctx, android.BuildParams{ 598 Rule: dumpRule, 599 Description: "header-abi-dumper " + srcFile.Rel(), 600 Output: sAbiDumpFile, 601 Input: srcFile, 602 Implicit: objFile, 603 Implicits: cFlagsDeps, 604 OrderOnly: pathDeps, 605 Args: map[string]string{ 606 "cFlags": moduleToolingFlags, 607 "exportDirs": flags.sAbiFlags, 608 }, 609 }) 610 } 611 612 } 613 614 return Objects{ 615 objFiles: objFiles, 616 tidyFiles: tidyFiles, 617 coverageFiles: coverageFiles, 618 sAbiDumpFiles: sAbiDumpFiles, 619 kytheFiles: kytheFiles, 620 } 621} 622 623// Generate a rule for compiling multiple .o files to a static library (.a) 624func TransformObjToStaticLib(ctx android.ModuleContext, 625 objFiles android.Paths, wholeStaticLibs android.Paths, 626 flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) { 627 628 arCmd := "${config.ClangBin}/llvm-ar" 629 arFlags := "" 630 if !ctx.Darwin() { 631 arFlags += " -format=gnu" 632 } 633 634 if len(wholeStaticLibs) == 0 { 635 ctx.Build(pctx, android.BuildParams{ 636 Rule: ar, 637 Description: "static link " + outputFile.Base(), 638 Output: outputFile, 639 Inputs: objFiles, 640 Implicits: deps, 641 Args: map[string]string{ 642 "arFlags": "crsPD" + arFlags, 643 "arCmd": arCmd, 644 }, 645 }) 646 647 } else { 648 ctx.Build(pctx, android.BuildParams{ 649 Rule: arWithLibs, 650 Description: "static link " + outputFile.Base(), 651 Output: outputFile, 652 Inputs: append(objFiles, wholeStaticLibs...), 653 Implicits: deps, 654 Args: map[string]string{ 655 "arCmd": arCmd, 656 "arObjFlags": "crsPD" + arFlags, 657 "arObjs": strings.Join(objFiles.Strings(), " "), 658 "arLibFlags": "cqsL" + arFlags, 659 "arLibs": strings.Join(wholeStaticLibs.Strings(), " "), 660 }, 661 }) 662 } 663} 664 665// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries, 666// and shared libraries, to a shared library (.so) or dynamic executable 667func TransformObjToDynamicBinary(ctx android.ModuleContext, 668 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths, 669 crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath, implicitOutputs android.WritablePaths) { 670 671 ldCmd := "${config.ClangBin}/clang++" 672 673 var libFlagsList []string 674 675 if len(flags.libFlags) > 0 { 676 libFlagsList = append(libFlagsList, flags.libFlags) 677 } 678 679 if len(wholeStaticLibs) > 0 { 680 if ctx.Host() && ctx.Darwin() { 681 libFlagsList = append(libFlagsList, android.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load ")) 682 } else { 683 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ") 684 libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...) 685 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ") 686 } 687 } 688 689 if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 { 690 libFlagsList = append(libFlagsList, "-Wl,--start-group") 691 } 692 libFlagsList = append(libFlagsList, staticLibs.Strings()...) 693 if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 { 694 libFlagsList = append(libFlagsList, "-Wl,--end-group") 695 } 696 697 if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 { 698 libFlagsList = append(libFlagsList, "-Wl,--start-group") 699 } 700 libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...) 701 if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 { 702 libFlagsList = append(libFlagsList, "-Wl,--end-group") 703 } 704 705 for _, lib := range sharedLibs { 706 libFile := lib.String() 707 if ctx.Windows() { 708 libFile = pathtools.ReplaceExtension(libFile, "lib") 709 } 710 libFlagsList = append(libFlagsList, libFile) 711 } 712 713 deps = append(deps, staticLibs...) 714 deps = append(deps, lateStaticLibs...) 715 deps = append(deps, wholeStaticLibs...) 716 if crtBegin.Valid() { 717 deps = append(deps, crtBegin.Path(), crtEnd.Path()) 718 } 719 720 rule := ld 721 args := map[string]string{ 722 "ldCmd": ldCmd, 723 "crtBegin": crtBegin.String(), 724 "libFlags": strings.Join(libFlagsList, " "), 725 "extraLibFlags": flags.extraLibFlags, 726 "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags, 727 "crtEnd": crtEnd.String(), 728 } 729 if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") { 730 rule = ldRE 731 args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",") 732 } 733 734 ctx.Build(pctx, android.BuildParams{ 735 Rule: rule, 736 Description: "link " + outputFile.Base(), 737 Output: outputFile, 738 ImplicitOutputs: implicitOutputs, 739 Inputs: objFiles, 740 Implicits: deps, 741 Args: args, 742 }) 743} 744 745// Generate a rule to combine .dump sAbi dump files from multiple source files 746// into a single .ldump sAbi dump file 747func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path, 748 baseName, exportedHeaderFlags string, symbolFile android.OptionalPath, 749 excludedSymbolVersions, excludedSymbolTags []string) android.OptionalPath { 750 751 outputFile := android.PathForModuleOut(ctx, baseName+".lsdump") 752 753 implicits := android.Paths{soFile} 754 symbolFilterStr := "-so " + soFile.String() 755 756 if symbolFile.Valid() { 757 implicits = append(implicits, symbolFile.Path()) 758 symbolFilterStr += " -v " + symbolFile.String() 759 } 760 for _, ver := range excludedSymbolVersions { 761 symbolFilterStr += " --exclude-symbol-version " + ver 762 } 763 for _, tag := range excludedSymbolTags { 764 symbolFilterStr += " --exclude-symbol-tag " + tag 765 } 766 rule := sAbiLink 767 args := map[string]string{ 768 "symbolFilter": symbolFilterStr, 769 "arch": ctx.Arch().ArchType.Name, 770 "exportedHeaderFlags": exportedHeaderFlags, 771 } 772 if ctx.Config().IsEnvTrue("RBE_ABI_LINKER") { 773 rule = sAbiLinkRE 774 rbeImplicits := implicits.Strings() 775 for _, p := range strings.Split(exportedHeaderFlags, " ") { 776 if len(p) > 2 { 777 // Exclude the -I prefix. 778 rbeImplicits = append(rbeImplicits, p[2:]) 779 } 780 } 781 args["implicits"] = strings.Join(rbeImplicits, ",") 782 } 783 ctx.Build(pctx, android.BuildParams{ 784 Rule: rule, 785 Description: "header-abi-linker " + outputFile.Base(), 786 Output: outputFile, 787 Inputs: sAbiDumps, 788 Implicits: implicits, 789 Args: args, 790 }) 791 return android.OptionalPathForPath(outputFile) 792} 793 794func UnzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path { 795 outputFile := android.PathForModuleOut(ctx, baseName+"_ref.lsdump") 796 ctx.Build(pctx, android.BuildParams{ 797 Rule: unzipRefSAbiDump, 798 Description: "gunzip" + outputFile.Base(), 799 Output: outputFile, 800 Input: zippedRefDump, 801 }) 802 return outputFile 803} 804 805func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path, 806 baseName, exportedHeaderFlags string, checkAllApis, isLlndk, isNdk, isVndkExt bool) android.OptionalPath { 807 808 outputFile := android.PathForModuleOut(ctx, baseName+".abidiff") 809 libName := strings.TrimSuffix(baseName, filepath.Ext(baseName)) 810 createReferenceDumpFlags := "" 811 812 var extraFlags []string 813 if checkAllApis { 814 extraFlags = append(extraFlags, "-check-all-apis") 815 } else { 816 extraFlags = append(extraFlags, 817 "-allow-unreferenced-changes", 818 "-allow-unreferenced-elf-symbol-changes") 819 } 820 821 if exportedHeaderFlags == "" { 822 extraFlags = append(extraFlags, "-advice-only") 823 } 824 825 if isLlndk || isNdk { 826 createReferenceDumpFlags = "--llndk" 827 if isLlndk { 828 // TODO(b/130324828): "-consider-opaque-types-different" should apply to 829 // both LLNDK and NDK shared libs. However, a known issue in header-abi-diff 830 // breaks libaaudio. Remove the if-guard after the issue is fixed. 831 extraFlags = append(extraFlags, "-consider-opaque-types-different") 832 } 833 } 834 if isVndkExt { 835 extraFlags = append(extraFlags, "-allow-extensions") 836 } 837 838 ctx.Build(pctx, android.BuildParams{ 839 Rule: sAbiDiff, 840 Description: "header-abi-diff " + outputFile.Base(), 841 Output: outputFile, 842 Input: inputDump, 843 Implicit: referenceDump, 844 Args: map[string]string{ 845 "referenceDump": referenceDump.String(), 846 "libName": libName, 847 "arch": ctx.Arch().ArchType.Name, 848 "extraFlags": strings.Join(extraFlags, " "), 849 "createReferenceDumpFlags": createReferenceDumpFlags, 850 }, 851 }) 852 return android.OptionalPathForPath(outputFile) 853} 854 855// Generate a rule for extracting a table of contents from a shared library (.so) 856func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path, 857 outputFile android.WritablePath, flags builderFlags) { 858 859 var format string 860 var crossCompile string 861 if ctx.Darwin() { 862 format = "--macho" 863 crossCompile = "${config.MacToolPath}" 864 } else if ctx.Windows() { 865 format = "--pe" 866 crossCompile = gccCmd(flags.toolchain, "") 867 } else { 868 format = "--elf" 869 crossCompile = gccCmd(flags.toolchain, "") 870 } 871 872 ctx.Build(pctx, android.BuildParams{ 873 Rule: toc, 874 Description: "generate toc " + inputFile.Base(), 875 Output: outputFile, 876 Input: inputFile, 877 Args: map[string]string{ 878 "crossCompile": crossCompile, 879 "format": format, 880 }, 881 }) 882} 883 884// Generate a rule for compiling multiple .o files to a .o using ld partial linking 885func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths, 886 flags builderFlags, outputFile android.WritablePath, deps android.Paths) { 887 888 ldCmd := "${config.ClangBin}/clang++" 889 890 rule := partialLd 891 args := map[string]string{ 892 "ldCmd": ldCmd, 893 "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags, 894 } 895 if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") { 896 rule = partialLdRE 897 args["inCommaList"] = strings.Join(objFiles.Strings(), ",") 898 } 899 ctx.Build(pctx, android.BuildParams{ 900 Rule: rule, 901 Description: "link " + outputFile.Base(), 902 Output: outputFile, 903 Inputs: objFiles, 904 Implicits: deps, 905 Args: args, 906 }) 907} 908 909// Generate a rule for runing objcopy --prefix-symbols on a binary 910func TransformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path, 911 flags builderFlags, outputFile android.WritablePath) { 912 913 objcopyCmd := gccCmd(flags.toolchain, "objcopy") 914 915 ctx.Build(pctx, android.BuildParams{ 916 Rule: prefixSymbols, 917 Description: "prefix symbols " + outputFile.Base(), 918 Output: outputFile, 919 Input: inputFile, 920 Args: map[string]string{ 921 "objcopyCmd": objcopyCmd, 922 "prefix": prefix, 923 }, 924 }) 925} 926 927func TransformStrip(ctx android.ModuleContext, inputFile android.Path, 928 outputFile android.WritablePath, flags builderFlags) { 929 930 crossCompile := gccCmd(flags.toolchain, "") 931 args := "" 932 if flags.stripAddGnuDebuglink { 933 args += " --add-gnu-debuglink" 934 } 935 if flags.stripKeepMiniDebugInfo { 936 args += " --keep-mini-debug-info" 937 } 938 if flags.stripKeepSymbols { 939 args += " --keep-symbols" 940 } 941 if flags.stripKeepSymbolsList != "" { 942 args += " -k" + flags.stripKeepSymbolsList 943 } 944 if flags.stripKeepSymbolsAndDebugFrame { 945 args += " --keep-symbols-and-debug-frame" 946 } 947 if flags.stripUseGnuStrip { 948 args += " --use-gnu-strip" 949 } 950 951 ctx.Build(pctx, android.BuildParams{ 952 Rule: strip, 953 Description: "strip " + outputFile.Base(), 954 Output: outputFile, 955 Input: inputFile, 956 Args: map[string]string{ 957 "crossCompile": crossCompile, 958 "args": args, 959 }, 960 }) 961} 962 963func TransformDarwinStrip(ctx android.ModuleContext, inputFile android.Path, 964 outputFile android.WritablePath) { 965 966 ctx.Build(pctx, android.BuildParams{ 967 Rule: darwinStrip, 968 Description: "strip " + outputFile.Base(), 969 Output: outputFile, 970 Input: inputFile, 971 }) 972} 973 974func TransformCoverageFilesToZip(ctx android.ModuleContext, 975 inputs Objects, baseName string) android.OptionalPath { 976 977 if len(inputs.coverageFiles) > 0 { 978 outputFile := android.PathForModuleOut(ctx, baseName+".zip") 979 980 ctx.Build(pctx, android.BuildParams{ 981 Rule: zip, 982 Description: "zip " + outputFile.Base(), 983 Inputs: inputs.coverageFiles, 984 Output: outputFile, 985 }) 986 987 return android.OptionalPathForPath(outputFile) 988 } 989 990 return android.OptionalPath{} 991} 992 993func TransformArchiveRepack(ctx android.ModuleContext, inputFile android.Path, 994 outputFile android.WritablePath, objects []string) { 995 996 ctx.Build(pctx, android.BuildParams{ 997 Rule: archiveRepack, 998 Description: "Repack archive " + outputFile.Base(), 999 Output: outputFile, 1000 Input: inputFile, 1001 Args: map[string]string{ 1002 "objects": strings.Join(objects, " "), 1003 }, 1004 }) 1005} 1006 1007func gccCmd(toolchain config.Toolchain, cmd string) string { 1008 return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd) 1009} 1010 1011func splitListForSize(list android.Paths, limit int) (lists []android.Paths, err error) { 1012 var i int 1013 1014 start := 0 1015 bytes := 0 1016 for i = range list { 1017 l := len(list[i].String()) 1018 if l > limit { 1019 return nil, fmt.Errorf("list element greater than size limit (%d)", limit) 1020 } 1021 if bytes+l > limit { 1022 lists = append(lists, list[start:i]) 1023 start = i 1024 bytes = 0 1025 } 1026 bytes += l + 1 // count a space between each list element 1027 } 1028 1029 lists = append(lists, list[start:]) 1030 1031 totalLen := 0 1032 for _, l := range lists { 1033 totalLen += len(l) 1034 } 1035 if totalLen != len(list) { 1036 panic(fmt.Errorf("Failed breaking up list, %d != %d", len(list), totalLen)) 1037 } 1038 return lists, nil 1039} 1040