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