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