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 ModuleContext, subdir string, srcFiles, noTidySrcs, timeoutTidySrcs android.Paths, 476 flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects { 477 // Source files are one-to-one with tidy, coverage, or kythe files, if enabled. 478 objFiles := make(android.Paths, len(srcFiles)) 479 var tidyFiles android.Paths 480 noTidySrcsMap := make(map[string]bool) 481 var tidyVars string 482 if flags.tidy { 483 tidyFiles = make(android.Paths, 0, len(srcFiles)) 484 for _, path := range noTidySrcs { 485 noTidySrcsMap[path.String()] = true 486 } 487 tidyTimeout := ctx.Config().Getenv("TIDY_TIMEOUT") 488 if len(tidyTimeout) > 0 { 489 tidyVars += "TIDY_TIMEOUT=" + tidyTimeout + " " 490 // add timeoutTidySrcs into noTidySrcsMap if TIDY_TIMEOUT is set 491 for _, path := range timeoutTidySrcs { 492 noTidySrcsMap[path.String()] = true 493 } 494 } 495 } 496 var coverageFiles android.Paths 497 if flags.gcovCoverage { 498 coverageFiles = make(android.Paths, 0, len(srcFiles)) 499 } 500 var kytheFiles android.Paths 501 if flags.emitXrefs && ctx.Module() == ctx.PrimaryModule() { 502 kytheFiles = make(android.Paths, 0, len(srcFiles)) 503 } 504 505 // Produce fully expanded flags for use by C tools, C compiles, C++ tools, C++ compiles, and asm compiles 506 // respectively. 507 toolingCflags := flags.globalCommonFlags + " " + 508 flags.globalToolingCFlags + " " + 509 flags.globalConlyFlags + " " + 510 flags.localCommonFlags + " " + 511 flags.localToolingCFlags + " " + 512 flags.localConlyFlags + " " + 513 flags.systemIncludeFlags + " " + 514 flags.noOverrideFlags 515 516 cflags := flags.globalCommonFlags + " " + 517 flags.globalCFlags + " " + 518 flags.globalConlyFlags + " " + 519 flags.localCommonFlags + " " + 520 flags.localCFlags + " " + 521 flags.localConlyFlags + " " + 522 flags.systemIncludeFlags + " " + 523 flags.noOverrideFlags 524 525 toolingCppflags := flags.globalCommonFlags + " " + 526 flags.globalToolingCFlags + " " + 527 flags.globalToolingCppFlags + " " + 528 flags.localCommonFlags + " " + 529 flags.localToolingCFlags + " " + 530 flags.localToolingCppFlags + " " + 531 flags.systemIncludeFlags + " " + 532 flags.noOverrideFlags 533 534 cppflags := flags.globalCommonFlags + " " + 535 flags.globalCFlags + " " + 536 flags.globalCppFlags + " " + 537 flags.localCommonFlags + " " + 538 flags.localCFlags + " " + 539 flags.localCppFlags + " " + 540 flags.systemIncludeFlags + " " + 541 flags.noOverrideFlags 542 543 asflags := flags.globalCommonFlags + " " + 544 flags.globalAsFlags + " " + 545 flags.localCommonFlags + " " + 546 flags.localAsFlags + " " + 547 flags.systemIncludeFlags 548 549 var sAbiDumpFiles android.Paths 550 if flags.sAbiDump { 551 sAbiDumpFiles = make(android.Paths, 0, len(srcFiles)) 552 } 553 554 // Multiple source files have build rules usually share the same cFlags or tidyFlags. 555 // Define only one version in this module and share it in multiple build rules. 556 // To simplify the code, the shared variables are all named as $flags<nnn>. 557 shared := ctx.getSharedFlags() 558 559 // Share flags only when there are multiple files or tidy rules. 560 var hasMultipleRules = len(srcFiles) > 1 || flags.tidy 561 562 var shareFlags = func(kind string, flags string) string { 563 if !hasMultipleRules || len(flags) < 60 { 564 // Modules have long names and so do the module variables. 565 // It does not save space by replacing a short name with a long one. 566 return flags 567 } 568 mapKey := kind + flags 569 n, ok := shared.flagsMap[mapKey] 570 if !ok { 571 shared.numSharedFlags += 1 572 n = strconv.Itoa(shared.numSharedFlags) 573 shared.flagsMap[mapKey] = n 574 ctx.Variable(pctx, kind+n, flags) 575 } 576 return "$" + kind + n 577 } 578 579 for i, srcFile := range srcFiles { 580 objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o") 581 582 objFiles[i] = objFile 583 584 // Register compilation build statements. The actual rule used depends on the source file type. 585 switch srcFile.Ext() { 586 case ".asm": 587 ctx.Build(pctx, android.BuildParams{ 588 Rule: yasm, 589 Description: "yasm " + srcFile.Rel(), 590 Output: objFile, 591 Input: srcFile, 592 Implicits: cFlagsDeps, 593 OrderOnly: pathDeps, 594 Args: map[string]string{ 595 "asFlags": shareFlags("asFlags", flags.globalYasmFlags+" "+flags.localYasmFlags), 596 }, 597 }) 598 continue 599 case ".o": 600 objFiles[i] = srcFile 601 continue 602 } 603 604 var moduleFlags string 605 var moduleToolingFlags string 606 607 var ccCmd string 608 var postCmd string 609 tidy := flags.tidy 610 coverage := flags.gcovCoverage 611 dump := flags.sAbiDump 612 rule := cc 613 emitXref := flags.emitXrefs 614 615 switch srcFile.Ext() { 616 case ".s": 617 if !flags.assemblerWithCpp { 618 rule = ccNoDeps 619 } 620 fallthrough 621 case ".S": 622 ccCmd = "clang" 623 moduleFlags = asflags 624 tidy = false 625 coverage = false 626 dump = false 627 emitXref = false 628 case ".c": 629 ccCmd = "clang" 630 moduleFlags = cflags 631 moduleToolingFlags = toolingCflags 632 case ".cpp", ".cc", ".cxx", ".mm": 633 ccCmd = "clang++" 634 moduleFlags = cppflags 635 moduleToolingFlags = toolingCppflags 636 case ".rs": 637 // A source provider (e.g. rust_bindgen) may provide both rs and c files. 638 // Ignore the rs files. 639 continue 640 case ".h", ".hpp": 641 ctx.PropertyErrorf("srcs", "Header file %s is not supported, instead use export_include_dirs or local_include_dirs.", srcFile) 642 continue 643 default: 644 ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .s, .S, .c, .cpp, .cc, .cxx, .mm", srcFile) 645 continue 646 } 647 648 // ccCmd is "clang" or "clang++" 649 ccDesc := ccCmd 650 651 ccCmd = "${config.ClangBin}/" + ccCmd 652 653 if flags.clangVerify { 654 postCmd = " && touch " + objFile.String() 655 } 656 657 var implicitOutputs android.WritablePaths 658 if coverage { 659 gcnoFile := android.ObjPathWithExt(ctx, subdir, srcFile, "gcno") 660 implicitOutputs = append(implicitOutputs, gcnoFile) 661 coverageFiles = append(coverageFiles, gcnoFile) 662 } 663 664 ctx.Build(pctx, android.BuildParams{ 665 Rule: rule, 666 Description: ccDesc + " " + srcFile.Rel(), 667 Output: objFile, 668 ImplicitOutputs: implicitOutputs, 669 Input: srcFile, 670 Implicits: cFlagsDeps, 671 OrderOnly: pathDeps, 672 Args: map[string]string{ 673 "cFlags": shareFlags("cFlags", moduleFlags), 674 "ccCmd": ccCmd, // short and not shared 675 "postCmd": postCmd, 676 }, 677 }) 678 679 // Register post-process build statements (such as for tidy or kythe). 680 if emitXref && ctx.Module() == ctx.PrimaryModule() { 681 kytheFile := android.ObjPathWithExt(ctx, subdir, srcFile, "kzip") 682 ctx.Build(pctx, android.BuildParams{ 683 Rule: kytheExtract, 684 Description: "Xref C++ extractor " + srcFile.Rel(), 685 Output: kytheFile, 686 Input: srcFile, 687 Implicits: cFlagsDeps, 688 OrderOnly: pathDeps, 689 Args: map[string]string{ 690 "cFlags": shareFlags("cFlags", moduleFlags), 691 }, 692 }) 693 kytheFiles = append(kytheFiles, kytheFile) 694 } 695 696 // Even with tidy, some src file could be skipped by noTidySrcsMap. 697 if tidy && !noTidySrcsMap[srcFile.String()] { 698 tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy") 699 tidyFiles = append(tidyFiles, tidyFile) 700 tidyCmd := "${config.ClangBin}/clang-tidy" 701 702 rule := clangTidy 703 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CLANG_TIDY") { 704 rule = clangTidyRE 705 } 706 707 sharedCFlags := shareFlags("cFlags", moduleFlags) 708 srcRelPath := srcFile.Rel() 709 710 // Add the .tidy rule 711 ctx.Build(pctx, android.BuildParams{ 712 Rule: rule, 713 Description: "clang-tidy " + srcRelPath, 714 Output: tidyFile, 715 Input: srcFile, 716 Implicits: cFlagsDeps, 717 OrderOnly: pathDeps, 718 Args: map[string]string{ 719 "cFlags": sharedCFlags, 720 "ccCmd": ccCmd, 721 "clangCmd": ccDesc, 722 "tidyCmd": tidyCmd, 723 "tidyFlags": shareFlags("tidyFlags", config.TidyFlagsForSrcFile(srcFile, flags.tidyFlags)), 724 "tidyVars": tidyVars, // short and not shared 725 }, 726 }) 727 } 728 729 if dump { 730 sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump") 731 sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile) 732 733 dumpRule := sAbiDump 734 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_DUMPER") { 735 dumpRule = sAbiDumpRE 736 } 737 ctx.Build(pctx, android.BuildParams{ 738 Rule: dumpRule, 739 Description: "header-abi-dumper " + srcFile.Rel(), 740 Output: sAbiDumpFile, 741 Input: srcFile, 742 Implicit: objFile, 743 Implicits: cFlagsDeps, 744 OrderOnly: pathDeps, 745 Args: map[string]string{ 746 "cFlags": shareFlags("cFlags", moduleToolingFlags), 747 "exportDirs": shareFlags("exportDirs", flags.sAbiFlags), 748 }, 749 }) 750 } 751 752 } 753 754 var tidyDepFiles android.Paths 755 if flags.needTidyFiles { 756 tidyDepFiles = tidyFiles 757 } 758 return Objects{ 759 objFiles: objFiles, 760 tidyFiles: tidyFiles, 761 tidyDepFiles: tidyDepFiles, 762 coverageFiles: coverageFiles, 763 sAbiDumpFiles: sAbiDumpFiles, 764 kytheFiles: kytheFiles, 765 } 766} 767 768// Generate a rule for compiling multiple .o files to a static library (.a) 769func transformObjToStaticLib(ctx android.ModuleContext, 770 objFiles android.Paths, wholeStaticLibs android.Paths, 771 flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.Paths) { 772 773 arCmd := "${config.ClangBin}/llvm-ar" 774 arFlags := "" 775 if !ctx.Darwin() { 776 arFlags += " --format=gnu" 777 } 778 779 if len(wholeStaticLibs) == 0 { 780 ctx.Build(pctx, android.BuildParams{ 781 Rule: ar, 782 Description: "static link " + outputFile.Base(), 783 Output: outputFile, 784 Inputs: objFiles, 785 Implicits: deps, 786 Validations: validations, 787 Args: map[string]string{ 788 "arFlags": "crsPD" + arFlags, 789 "arCmd": arCmd, 790 }, 791 }) 792 793 } else { 794 ctx.Build(pctx, android.BuildParams{ 795 Rule: arWithLibs, 796 Description: "static link " + outputFile.Base(), 797 Output: outputFile, 798 Inputs: append(objFiles, wholeStaticLibs...), 799 Implicits: deps, 800 Args: map[string]string{ 801 "arCmd": arCmd, 802 "arObjFlags": "crsPD" + arFlags, 803 "arObjs": strings.Join(objFiles.Strings(), " "), 804 "arLibFlags": "cqsL" + arFlags, 805 "arLibs": strings.Join(wholeStaticLibs.Strings(), " "), 806 }, 807 }) 808 } 809} 810 811// Generate a Rust staticlib from a list of rlibDeps. Returns nil if TransformRlibstoStaticlib is nil or rlibDeps is empty. 812func generateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path { 813 if TransformRlibstoStaticlib == nil && len(rlibDeps) > 0 { 814 // This should only be reachable if a module defines Rust deps in static_libs and 815 // soong-rust hasn't been loaded alongside soong-cc (e.g. in soong-cc tests). 816 panic(fmt.Errorf( 817 "TransformRlibstoStaticlib is not set and rust deps are defined in static_libs for %s", 818 ctx.ModuleName())) 819 820 } else if len(rlibDeps) == 0 { 821 return nil 822 } 823 824 output := android.PathForModuleOut(ctx, "generated_rust_staticlib", "librustlibs.a") 825 stemFile := output.ReplaceExtension(ctx, "rs") 826 crateNames := []string{} 827 828 // Collect crate names 829 for _, lib := range rlibDeps { 830 // Exclude libstd so this can support no_std builds. 831 if lib.CrateName != "libstd" { 832 crateNames = append(crateNames, lib.CrateName) 833 } 834 } 835 836 // Deduplicate any crateNames just to be safe 837 crateNames = android.FirstUniqueStrings(crateNames) 838 839 // Write the source file 840 android.WriteFileRule(ctx, stemFile, genRustStaticlibSrcFile(crateNames)) 841 842 return TransformRlibstoStaticlib(ctx, stemFile, rlibDeps, output) 843} 844 845func genRustStaticlibSrcFile(crateNames []string) string { 846 lines := []string{ 847 "// @Soong generated Source", 848 "#![no_std]", // pre-emptively set no_std to support both std and no_std. 849 } 850 for _, crate := range crateNames { 851 lines = append(lines, fmt.Sprintf("extern crate %s;", crate)) 852 } 853 return strings.Join(lines, "\n") 854} 855 856// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries, 857// and shared libraries, to a shared library (.so) or dynamic executable 858func transformObjToDynamicBinary(ctx android.ModuleContext, 859 objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps, crtBegin, crtEnd android.Paths, 860 groupLate bool, flags builderFlags, outputFile android.WritablePath, 861 implicitOutputs android.WritablePaths, validations android.Paths) { 862 863 ldCmd := "${config.ClangBin}/clang++" 864 865 var libFlagsList []string 866 867 if len(flags.libFlags) > 0 { 868 libFlagsList = append(libFlagsList, flags.libFlags) 869 } 870 871 if len(wholeStaticLibs) > 0 { 872 if ctx.Host() && ctx.Darwin() { 873 libFlagsList = append(libFlagsList, android.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load ")) 874 } else { 875 libFlagsList = append(libFlagsList, "-Wl,--whole-archive ") 876 libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...) 877 libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ") 878 } 879 } 880 881 libFlagsList = append(libFlagsList, staticLibs.Strings()...) 882 883 if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 { 884 libFlagsList = append(libFlagsList, "-Wl,--start-group") 885 } 886 libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...) 887 if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 { 888 libFlagsList = append(libFlagsList, "-Wl,--end-group") 889 } 890 891 for _, lib := range sharedLibs { 892 libFile := lib.String() 893 if ctx.Windows() { 894 libFile = pathtools.ReplaceExtension(libFile, "lib") 895 } 896 libFlagsList = append(libFlagsList, libFile) 897 } 898 899 deps = append(deps, staticLibs...) 900 deps = append(deps, lateStaticLibs...) 901 deps = append(deps, wholeStaticLibs...) 902 deps = append(deps, crtBegin...) 903 deps = append(deps, crtEnd...) 904 905 rule := ld 906 args := map[string]string{ 907 "ldCmd": ldCmd, 908 "crtBegin": strings.Join(crtBegin.Strings(), " "), 909 "libFlags": strings.Join(libFlagsList, " "), 910 "extraLibFlags": flags.extraLibFlags, 911 "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags, 912 "crtEnd": strings.Join(crtEnd.Strings(), " "), 913 } 914 915 // On Windows, we always generate a PDB file 916 // --strip-debug is needed to also keep COFF symbols which are needed when 917 // we patch binaries with symbol_inject. 918 if ctx.Windows() { 919 pdb := outputFile.ReplaceExtension(ctx, "pdb") 920 args["ldFlags"] = args["ldFlags"] + " -Wl,--strip-debug -Wl,--pdb=" + pdb.String() + " " 921 implicitOutputs = append(slices.Clone(implicitOutputs), pdb) 922 } 923 924 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") { 925 rule = ldRE 926 args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",") 927 args["implicitInputs"] = strings.Join(deps.Strings(), ",") 928 } 929 930 ctx.Build(pctx, android.BuildParams{ 931 Rule: rule, 932 Description: "link " + outputFile.Base(), 933 Output: outputFile, 934 ImplicitOutputs: implicitOutputs, 935 Inputs: objFiles, 936 Implicits: deps, 937 OrderOnly: sharedLibs, 938 Validations: validations, 939 Args: args, 940 }) 941} 942 943// Generate a rule to combine .dump sAbi dump files from multiple source files 944// into a single .ldump sAbi dump file 945func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path, 946 baseName string, exportedIncludeDirs []string, symbolFile android.OptionalPath, 947 excludedSymbolVersions, excludedSymbolTags, includedSymbolTags []string, 948 api string) android.Path { 949 950 outputFile := android.PathForModuleOut(ctx, baseName+".lsdump") 951 952 implicits := android.Paths{soFile} 953 symbolFilterStr := "-so " + soFile.String() 954 exportedHeaderFlags := android.JoinWithPrefix(exportedIncludeDirs, "-I") 955 956 if symbolFile.Valid() { 957 implicits = append(implicits, symbolFile.Path()) 958 symbolFilterStr += " -v " + symbolFile.String() 959 } 960 for _, ver := range excludedSymbolVersions { 961 symbolFilterStr += " --exclude-symbol-version " + ver 962 } 963 for _, tag := range excludedSymbolTags { 964 symbolFilterStr += " --exclude-symbol-tag " + tag 965 } 966 for _, tag := range includedSymbolTags { 967 symbolFilterStr += " --include-symbol-tag " + tag 968 } 969 apiLevelsJson := android.GetApiLevelsJson(ctx) 970 implicits = append(implicits, apiLevelsJson) 971 symbolFilterStr += " --api-map " + apiLevelsJson.String() 972 symbolFilterStr += " --api " + api 973 974 rule := sAbiLink 975 args := map[string]string{ 976 "symbolFilter": symbolFilterStr, 977 "arch": ctx.Arch().ArchType.Name, 978 "exportedHeaderFlags": exportedHeaderFlags, 979 } 980 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_LINKER") { 981 rule = sAbiLinkRE 982 rbeImplicits := append(implicits.Strings(), exportedIncludeDirs...) 983 args["implicitInputs"] = strings.Join(rbeImplicits, ",") 984 } 985 ctx.Build(pctx, android.BuildParams{ 986 Rule: rule, 987 Description: "header-abi-linker " + outputFile.Base(), 988 Output: outputFile, 989 Inputs: sAbiDumps, 990 Implicits: implicits, 991 Args: args, 992 }) 993 return outputFile 994} 995 996func transformAbiDumpToAbiDiff(ctx android.ModuleContext, inputDump, referenceDump android.Path, 997 baseName, nameExt string, extraFlags []string, errorMessage string) android.Path { 998 999 var outputFile android.ModuleOutPath 1000 if nameExt != "" { 1001 outputFile = android.PathForModuleOut(ctx, baseName+"."+nameExt+".abidiff") 1002 } else { 1003 outputFile = android.PathForModuleOut(ctx, baseName+".abidiff") 1004 } 1005 libName := strings.TrimSuffix(baseName, filepath.Ext(baseName)) 1006 1007 ctx.Build(pctx, android.BuildParams{ 1008 Rule: sAbiDiff, 1009 Description: "header-abi-diff " + outputFile.Base(), 1010 Output: outputFile, 1011 Input: inputDump, 1012 Implicit: referenceDump, 1013 Args: map[string]string{ 1014 "referenceDump": referenceDump.String(), 1015 "libName": libName, 1016 "arch": ctx.Arch().ArchType.Name, 1017 "extraFlags": strings.Join(extraFlags, " "), 1018 "errorMessage": errorMessage, 1019 }, 1020 }) 1021 return outputFile 1022} 1023 1024// Generate a rule for extracting a table of contents from a shared library (.so) 1025func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) { 1026 1027 var format string 1028 if ctx.Darwin() { 1029 format = "--macho" 1030 } else if ctx.Windows() { 1031 format = "--pe" 1032 } else { 1033 format = "--elf" 1034 } 1035 1036 ctx.Build(pctx, android.BuildParams{ 1037 Rule: toc, 1038 Description: "generate toc " + inputFile.Base(), 1039 Output: outputFile, 1040 Input: inputFile, 1041 Args: map[string]string{ 1042 "clangBin": "${config.ClangBin}", 1043 "format": format, 1044 }, 1045 }) 1046} 1047 1048// Generate a rule for compiling multiple .o files to a .o using ld partial linking 1049func transformObjsToObj(ctx android.ModuleContext, objFiles android.Paths, 1050 flags builderFlags, outputFile android.WritablePath, deps android.Paths) { 1051 1052 ldCmd := "${config.ClangBin}/clang++" 1053 1054 rule := partialLd 1055 args := map[string]string{ 1056 "ldCmd": ldCmd, 1057 "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags, 1058 } 1059 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") { 1060 rule = partialLdRE 1061 args["inCommaList"] = strings.Join(objFiles.Strings(), ",") 1062 args["implicitInputs"] = strings.Join(deps.Strings(), ",") 1063 } 1064 ctx.Build(pctx, android.BuildParams{ 1065 Rule: rule, 1066 Description: "link " + outputFile.Base(), 1067 Output: outputFile, 1068 Inputs: objFiles, 1069 Implicits: deps, 1070 Args: args, 1071 }) 1072} 1073 1074// Generate a rule for running objcopy --prefix-symbols on a binary 1075func transformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path, 1076 flags builderFlags, outputFile android.WritablePath) { 1077 1078 objcopyCmd := "${config.ClangBin}/llvm-objcopy" 1079 1080 ctx.Build(pctx, android.BuildParams{ 1081 Rule: prefixSymbols, 1082 Description: "prefix symbols " + outputFile.Base(), 1083 Output: outputFile, 1084 Input: inputFile, 1085 Args: map[string]string{ 1086 "objcopyCmd": objcopyCmd, 1087 "prefix": prefix, 1088 }, 1089 }) 1090} 1091 1092// Generate a rule for running objcopy --remove-section=.llvm_addrsig on a partially linked object 1093func transformObjectNoAddrSig(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) { 1094 objcopyCmd := "${config.ClangBin}/llvm-objcopy" 1095 1096 ctx.Build(pctx, android.BuildParams{ 1097 Rule: noAddrSig, 1098 Description: "remove addrsig " + outputFile.Base(), 1099 Output: outputFile, 1100 Input: inputFile, 1101 Args: map[string]string{ 1102 "objcopyCmd": objcopyCmd, 1103 }, 1104 }) 1105} 1106 1107// Registers a build statement to invoke `strip` (to discard symbols and data from object files). 1108func transformStrip(ctx android.ModuleContext, inputFile android.Path, 1109 outputFile android.WritablePath, flags StripFlags) { 1110 1111 args := "" 1112 if flags.StripAddGnuDebuglink { 1113 args += " --add-gnu-debuglink" 1114 } 1115 if flags.StripKeepMiniDebugInfo { 1116 args += " --keep-mini-debug-info" 1117 } 1118 if flags.StripKeepSymbols { 1119 args += " --keep-symbols" 1120 } 1121 if flags.StripKeepSymbolsList != "" { 1122 args += " -k" + flags.StripKeepSymbolsList 1123 } 1124 if flags.StripKeepSymbolsAndDebugFrame { 1125 args += " --keep-symbols-and-debug-frame" 1126 } 1127 if ctx.Windows() { 1128 args += " --windows" 1129 } 1130 1131 ctx.Build(pctx, android.BuildParams{ 1132 Rule: strip, 1133 Description: "strip " + outputFile.Base(), 1134 Output: outputFile, 1135 Input: inputFile, 1136 Args: map[string]string{ 1137 "args": args, 1138 }, 1139 }) 1140} 1141 1142// Registers build statement to invoke `strip` on darwin architecture. 1143func transformDarwinStrip(ctx android.ModuleContext, inputFile android.Path, 1144 outputFile android.WritablePath) { 1145 1146 ctx.Build(pctx, android.BuildParams{ 1147 Rule: darwinStrip, 1148 Description: "strip " + outputFile.Base(), 1149 Output: outputFile, 1150 Input: inputFile, 1151 }) 1152} 1153 1154func transformDarwinUniversalBinary(ctx android.ModuleContext, outputFile android.WritablePath, inputFiles ...android.Path) { 1155 ctx.Build(pctx, android.BuildParams{ 1156 Rule: darwinLipo, 1157 Description: "lipo " + outputFile.Base(), 1158 Output: outputFile, 1159 Inputs: inputFiles, 1160 }) 1161} 1162 1163// Registers build statement to zip one or more coverage files. 1164func transformCoverageFilesToZip(ctx android.ModuleContext, 1165 inputs Objects, baseName string) android.OptionalPath { 1166 1167 if len(inputs.coverageFiles) > 0 { 1168 outputFile := android.PathForModuleOut(ctx, baseName+".zip") 1169 1170 ctx.Build(pctx, android.BuildParams{ 1171 Rule: zip, 1172 Description: "zip " + outputFile.Base(), 1173 Inputs: inputs.coverageFiles, 1174 Output: outputFile, 1175 }) 1176 1177 return android.OptionalPathForPath(outputFile) 1178 } 1179 1180 return android.OptionalPath{} 1181} 1182 1183// Rule to repack an archive (.a) file with a subset of object files. 1184func transformArchiveRepack(ctx android.ModuleContext, inputFile android.Path, 1185 outputFile android.WritablePath, objects []string) { 1186 1187 ctx.Build(pctx, android.BuildParams{ 1188 Rule: archiveRepack, 1189 Description: "Repack archive " + outputFile.Base(), 1190 Output: outputFile, 1191 Input: inputFile, 1192 Args: map[string]string{ 1193 "objects": strings.Join(objects, " "), 1194 }, 1195 }) 1196} 1197