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