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