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