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