1// Copyright (C) 2018 The Android Open Source Project 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 apex 16 17import ( 18 "fmt" 19 "io" 20 "path/filepath" 21 "runtime" 22 "sort" 23 "strings" 24 25 "android/soong/android" 26 "android/soong/cc" 27 "android/soong/java" 28 "android/soong/python" 29 30 "github.com/google/blueprint" 31 "github.com/google/blueprint/bootstrap" 32 "github.com/google/blueprint/proptools" 33) 34 35var ( 36 pctx = android.NewPackageContext("android/apex") 37 38 // Create a canned fs config file where all files and directories are 39 // by default set to (uid/gid/mode) = (1000/1000/0644) 40 // TODO(b/113082813) make this configurable using config.fs syntax 41 generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{ 42 Command: `echo '/ 1000 1000 0755' > ${out} && ` + 43 `echo '/apex_manifest.json 1000 1000 0644' >> ${out} && ` + 44 `echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` + 45 `echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 0 2000 0755"}' >> ${out}`, 46 Description: "fs_config ${out}", 47 }, "ro_paths", "exec_paths") 48 49 // TODO(b/113233103): make sure that file_contexts is sane, i.e., validate 50 // against the binary policy using sefcontext_compiler -p <policy>. 51 52 // TODO(b/114327326): automate the generation of file_contexts 53 apexRule = pctx.StaticRule("apexRule", blueprint.RuleParams{ 54 Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + 55 `(${copy_commands}) && ` + 56 `APEXER_TOOL_PATH=${tool_path} ` + 57 `${apexer} --force --manifest ${manifest} ` + 58 `--file_contexts ${file_contexts} ` + 59 `--canned_fs_config ${canned_fs_config} ` + 60 `--payload_type image ` + 61 `--key ${key} ${opt_flags} ${image_dir} ${out} `, 62 CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}", 63 "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", 64 "${soong_zip}", "${zipalign}", "${aapt2}"}, 65 Description: "APEX ${image_dir} => ${out}", 66 }, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key", "opt_flags") 67 68 zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{ 69 Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + 70 `(${copy_commands}) && ` + 71 `APEXER_TOOL_PATH=${tool_path} ` + 72 `${apexer} --force --manifest ${manifest} ` + 73 `--payload_type zip ` + 74 `${image_dir} ${out} `, 75 CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"}, 76 Description: "ZipAPEX ${image_dir} => ${out}", 77 }, "tool_path", "image_dir", "copy_commands", "manifest") 78 79 apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule", 80 blueprint.RuleParams{ 81 Command: `${aapt2} convert --output-format proto $in -o $out`, 82 CommandDeps: []string{"${aapt2}"}, 83 }) 84 85 apexBundleRule = pctx.StaticRule("apexBundleRule", blueprint.RuleParams{ 86 Command: `${zip2zip} -i $in -o $out ` + 87 `apex_payload.img:apex/${abi}.img ` + 88 `apex_manifest.json:root/apex_manifest.json ` + 89 `AndroidManifest.xml:manifest/AndroidManifest.xml`, 90 CommandDeps: []string{"${zip2zip}"}, 91 Description: "app bundle", 92 }, "abi") 93) 94 95var imageApexSuffix = ".apex" 96var zipApexSuffix = ".zipapex" 97 98var imageApexType = "image" 99var zipApexType = "zip" 100 101type dependencyTag struct { 102 blueprint.BaseDependencyTag 103 name string 104} 105 106var ( 107 sharedLibTag = dependencyTag{name: "sharedLib"} 108 executableTag = dependencyTag{name: "executable"} 109 javaLibTag = dependencyTag{name: "javaLib"} 110 prebuiltTag = dependencyTag{name: "prebuilt"} 111 keyTag = dependencyTag{name: "key"} 112 certificateTag = dependencyTag{name: "certificate"} 113) 114 115func init() { 116 pctx.Import("android/soong/android") 117 pctx.Import("android/soong/java") 118 pctx.HostBinToolVariable("apexer", "apexer") 119 // ART minimal builds (using the master-art manifest) do not have the "frameworks/base" 120 // projects, and hence cannot built 'aapt2'. Use the SDK prebuilt instead. 121 hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) { 122 pctx.VariableFunc(name, func(ctx android.PackageVarContext) string { 123 if !ctx.Config().FrameworksBaseDirExists(ctx) { 124 return filepath.Join(prebuiltDir, runtime.GOOS, "bin", tool) 125 } else { 126 return pctx.HostBinToolPath(ctx, tool).String() 127 } 128 }) 129 } 130 hostBinToolVariableWithPrebuilt("aapt2", "prebuilts/sdk/tools", "aapt2") 131 pctx.HostBinToolVariable("avbtool", "avbtool") 132 pctx.HostBinToolVariable("e2fsdroid", "e2fsdroid") 133 pctx.HostBinToolVariable("merge_zips", "merge_zips") 134 pctx.HostBinToolVariable("mke2fs", "mke2fs") 135 pctx.HostBinToolVariable("resize2fs", "resize2fs") 136 pctx.HostBinToolVariable("sefcontext_compile", "sefcontext_compile") 137 pctx.HostBinToolVariable("soong_zip", "soong_zip") 138 pctx.HostBinToolVariable("zip2zip", "zip2zip") 139 pctx.HostBinToolVariable("zipalign", "zipalign") 140 141 android.RegisterModuleType("apex", apexBundleFactory) 142 android.RegisterModuleType("apex_test", testApexBundleFactory) 143 android.RegisterModuleType("apex_defaults", defaultsFactory) 144 android.RegisterModuleType("prebuilt_apex", PrebuiltFactory) 145 146 android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 147 ctx.TopDown("apex_deps", apexDepsMutator) 148 ctx.BottomUp("apex", apexMutator) 149 }) 150} 151 152// Mark the direct and transitive dependencies of apex bundles so that they 153// can be built for the apex bundles. 154func apexDepsMutator(mctx android.TopDownMutatorContext) { 155 if a, ok := mctx.Module().(*apexBundle); ok { 156 apexBundleName := mctx.ModuleName() 157 mctx.WalkDeps(func(child, parent android.Module) bool { 158 depName := mctx.OtherModuleName(child) 159 // If the parent is apexBundle, this child is directly depended. 160 _, directDep := parent.(*apexBundle) 161 if a.installable() && !a.testApex { 162 // TODO(b/123892969): Workaround for not having any way to annotate test-apexs 163 // non-installable apex's cannot be installed and so should not prevent libraries from being 164 // installed to the system. 165 android.UpdateApexDependency(apexBundleName, depName, directDep) 166 } 167 168 if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() { 169 am.BuildForApex(apexBundleName) 170 return true 171 } else { 172 return false 173 } 174 }) 175 } 176} 177 178// Create apex variations if a module is included in APEX(s). 179func apexMutator(mctx android.BottomUpMutatorContext) { 180 if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() { 181 am.CreateApexVariations(mctx) 182 } else if _, ok := mctx.Module().(*apexBundle); ok { 183 // apex bundle itself is mutated so that it and its modules have same 184 // apex variant. 185 apexBundleName := mctx.ModuleName() 186 mctx.CreateVariations(apexBundleName) 187 } 188} 189 190type apexNativeDependencies struct { 191 // List of native libraries 192 Native_shared_libs []string 193 // List of native executables 194 Binaries []string 195} 196type apexMultilibProperties struct { 197 // Native dependencies whose compile_multilib is "first" 198 First apexNativeDependencies 199 200 // Native dependencies whose compile_multilib is "both" 201 Both apexNativeDependencies 202 203 // Native dependencies whose compile_multilib is "prefer32" 204 Prefer32 apexNativeDependencies 205 206 // Native dependencies whose compile_multilib is "32" 207 Lib32 apexNativeDependencies 208 209 // Native dependencies whose compile_multilib is "64" 210 Lib64 apexNativeDependencies 211} 212 213type apexBundleProperties struct { 214 // Json manifest file describing meta info of this APEX bundle. Default: 215 // "apex_manifest.json" 216 Manifest *string `android:"path"` 217 218 // AndroidManifest.xml file used for the zip container of this APEX bundle. 219 // If unspecified, a default one is automatically generated. 220 AndroidManifest *string `android:"path"` 221 222 // Canonical name of the APEX bundle in the manifest file. 223 // If unspecified, defaults to the value of name 224 Apex_name *string 225 226 // Determines the file contexts file for setting security context to each file in this APEX bundle. 227 // Specifically, when this is set to <value>, /system/sepolicy/apex/<value>_file_contexts file is 228 // used. 229 // Default: <name_of_this_module> 230 File_contexts *string 231 232 // List of native shared libs that are embedded inside this APEX bundle 233 Native_shared_libs []string 234 235 // List of native executables that are embedded inside this APEX bundle 236 Binaries []string 237 238 // List of java libraries that are embedded inside this APEX bundle 239 Java_libs []string 240 241 // List of prebuilt files that are embedded inside this APEX bundle 242 Prebuilts []string 243 244 // Name of the apex_key module that provides the private key to sign APEX 245 Key *string 246 247 // The type of APEX to build. Controls what the APEX payload is. Either 248 // 'image', 'zip' or 'both'. Default: 'image'. 249 Payload_type *string 250 251 // The name of a certificate in the default certificate directory, blank to use the default product certificate, 252 // or an android_app_certificate module name in the form ":module". 253 Certificate *string 254 255 // Whether this APEX is installable to one of the partitions. Default: true. 256 Installable *bool 257 258 // For native libraries and binaries, use the vendor variant instead of the core (platform) variant. 259 // Default is false. 260 Use_vendor *bool 261 262 // For telling the apex to ignore special handling for system libraries such as bionic. Default is false. 263 Ignore_system_library_special_case *bool 264 265 Multilib apexMultilibProperties 266 267 // List of sanitizer names that this APEX is enabled for 268 SanitizerNames []string `blueprint:"mutated"` 269} 270 271type apexTargetBundleProperties struct { 272 Target struct { 273 // Multilib properties only for android. 274 Android struct { 275 Multilib apexMultilibProperties 276 } 277 // Multilib properties only for host. 278 Host struct { 279 Multilib apexMultilibProperties 280 } 281 // Multilib properties only for host linux_bionic. 282 Linux_bionic struct { 283 Multilib apexMultilibProperties 284 } 285 // Multilib properties only for host linux_glibc. 286 Linux_glibc struct { 287 Multilib apexMultilibProperties 288 } 289 } 290} 291 292type apexFileClass int 293 294const ( 295 etc apexFileClass = iota 296 nativeSharedLib 297 nativeExecutable 298 shBinary 299 pyBinary 300 goBinary 301 javaSharedLib 302) 303 304type apexPackaging int 305 306const ( 307 imageApex apexPackaging = iota 308 zipApex 309 both 310) 311 312func (a apexPackaging) image() bool { 313 switch a { 314 case imageApex, both: 315 return true 316 } 317 return false 318} 319 320func (a apexPackaging) zip() bool { 321 switch a { 322 case zipApex, both: 323 return true 324 } 325 return false 326} 327 328func (a apexPackaging) suffix() string { 329 switch a { 330 case imageApex: 331 return imageApexSuffix 332 case zipApex: 333 return zipApexSuffix 334 case both: 335 panic(fmt.Errorf("must be either zip or image")) 336 default: 337 panic(fmt.Errorf("unkonwn APEX type %d", a)) 338 } 339} 340 341func (a apexPackaging) name() string { 342 switch a { 343 case imageApex: 344 return imageApexType 345 case zipApex: 346 return zipApexType 347 case both: 348 panic(fmt.Errorf("must be either zip or image")) 349 default: 350 panic(fmt.Errorf("unkonwn APEX type %d", a)) 351 } 352} 353 354func (class apexFileClass) NameInMake() string { 355 switch class { 356 case etc: 357 return "ETC" 358 case nativeSharedLib: 359 return "SHARED_LIBRARIES" 360 case nativeExecutable, shBinary, pyBinary, goBinary: 361 return "EXECUTABLES" 362 case javaSharedLib: 363 return "JAVA_LIBRARIES" 364 default: 365 panic(fmt.Errorf("unkonwn class %d", class)) 366 } 367} 368 369type apexFile struct { 370 builtFile android.Path 371 moduleName string 372 installDir string 373 class apexFileClass 374 module android.Module 375 symlinks []string 376} 377 378type apexBundle struct { 379 android.ModuleBase 380 android.DefaultableModuleBase 381 382 properties apexBundleProperties 383 targetProperties apexTargetBundleProperties 384 385 apexTypes apexPackaging 386 387 bundleModuleFile android.WritablePath 388 outputFiles map[apexPackaging]android.WritablePath 389 installDir android.OutputPath 390 391 public_key_file android.Path 392 private_key_file android.Path 393 394 container_certificate_file android.Path 395 container_private_key_file android.Path 396 397 // list of files to be included in this apex 398 filesInfo []apexFile 399 400 // list of module names that this APEX is depending on 401 externalDeps []string 402 403 flattened bool 404 405 testApex bool 406} 407 408func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, 409 native_shared_libs []string, binaries []string, arch string, imageVariation string) { 410 // Use *FarVariation* to be able to depend on modules having 411 // conflicting variations with this module. This is required since 412 // arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64' 413 // for native shared libs. 414 ctx.AddFarVariationDependencies([]blueprint.Variation{ 415 {Mutator: "arch", Variation: arch}, 416 {Mutator: "image", Variation: imageVariation}, 417 {Mutator: "link", Variation: "shared"}, 418 {Mutator: "version", Variation: ""}, // "" is the non-stub variant 419 }, sharedLibTag, native_shared_libs...) 420 421 ctx.AddFarVariationDependencies([]blueprint.Variation{ 422 {Mutator: "arch", Variation: arch}, 423 {Mutator: "image", Variation: imageVariation}, 424 }, executableTag, binaries...) 425} 426 427func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) { 428 if ctx.Os().Class == android.Device { 429 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil) 430 } else { 431 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil) 432 if ctx.Os().Bionic() { 433 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil) 434 } else { 435 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil) 436 } 437 } 438} 439 440func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { 441 442 targets := ctx.MultiTargets() 443 config := ctx.DeviceConfig() 444 445 a.combineProperties(ctx) 446 447 has32BitTarget := false 448 for _, target := range targets { 449 if target.Arch.ArchType.Multilib == "lib32" { 450 has32BitTarget = true 451 } 452 } 453 for i, target := range targets { 454 // When multilib.* is omitted for native_shared_libs, it implies 455 // multilib.both. 456 ctx.AddFarVariationDependencies([]blueprint.Variation{ 457 {Mutator: "arch", Variation: target.String()}, 458 {Mutator: "image", Variation: a.getImageVariation(config)}, 459 {Mutator: "link", Variation: "shared"}, 460 }, sharedLibTag, a.properties.Native_shared_libs...) 461 462 // Add native modules targetting both ABIs 463 addDependenciesForNativeModules(ctx, 464 a.properties.Multilib.Both.Native_shared_libs, 465 a.properties.Multilib.Both.Binaries, target.String(), 466 a.getImageVariation(config)) 467 468 isPrimaryAbi := i == 0 469 if isPrimaryAbi { 470 // When multilib.* is omitted for binaries, it implies 471 // multilib.first. 472 ctx.AddFarVariationDependencies([]blueprint.Variation{ 473 {Mutator: "arch", Variation: target.String()}, 474 {Mutator: "image", Variation: a.getImageVariation(config)}, 475 }, executableTag, a.properties.Binaries...) 476 477 // Add native modules targetting the first ABI 478 addDependenciesForNativeModules(ctx, 479 a.properties.Multilib.First.Native_shared_libs, 480 a.properties.Multilib.First.Binaries, target.String(), 481 a.getImageVariation(config)) 482 483 // When multilib.* is omitted for prebuilts, it implies multilib.first. 484 ctx.AddFarVariationDependencies([]blueprint.Variation{ 485 {Mutator: "arch", Variation: target.String()}, 486 }, prebuiltTag, a.properties.Prebuilts...) 487 } 488 489 switch target.Arch.ArchType.Multilib { 490 case "lib32": 491 // Add native modules targetting 32-bit ABI 492 addDependenciesForNativeModules(ctx, 493 a.properties.Multilib.Lib32.Native_shared_libs, 494 a.properties.Multilib.Lib32.Binaries, target.String(), 495 a.getImageVariation(config)) 496 497 addDependenciesForNativeModules(ctx, 498 a.properties.Multilib.Prefer32.Native_shared_libs, 499 a.properties.Multilib.Prefer32.Binaries, target.String(), 500 a.getImageVariation(config)) 501 case "lib64": 502 // Add native modules targetting 64-bit ABI 503 addDependenciesForNativeModules(ctx, 504 a.properties.Multilib.Lib64.Native_shared_libs, 505 a.properties.Multilib.Lib64.Binaries, target.String(), 506 a.getImageVariation(config)) 507 508 if !has32BitTarget { 509 addDependenciesForNativeModules(ctx, 510 a.properties.Multilib.Prefer32.Native_shared_libs, 511 a.properties.Multilib.Prefer32.Binaries, target.String(), 512 a.getImageVariation(config)) 513 } 514 } 515 516 } 517 518 ctx.AddFarVariationDependencies([]blueprint.Variation{ 519 {Mutator: "arch", Variation: "android_common"}, 520 }, javaLibTag, a.properties.Java_libs...) 521 522 if String(a.properties.Key) == "" { 523 ctx.ModuleErrorf("key is missing") 524 return 525 } 526 ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key)) 527 528 cert := android.SrcIsModule(a.getCertString(ctx)) 529 if cert != "" { 530 ctx.AddDependency(ctx.Module(), certificateTag, cert) 531 } 532} 533 534func (a *apexBundle) getCertString(ctx android.BaseContext) string { 535 certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName()) 536 if overridden { 537 return ":" + certificate 538 } 539 return String(a.properties.Certificate) 540} 541 542func (a *apexBundle) Srcs() android.Paths { 543 if file, ok := a.outputFiles[imageApex]; ok { 544 return android.Paths{file} 545 } else { 546 return nil 547 } 548} 549 550func (a *apexBundle) installable() bool { 551 return a.properties.Installable == nil || proptools.Bool(a.properties.Installable) 552} 553 554func (a *apexBundle) getImageVariation(config android.DeviceConfig) string { 555 if config.VndkVersion() != "" && proptools.Bool(a.properties.Use_vendor) { 556 return "vendor" 557 } else { 558 return "core" 559 } 560} 561 562func (a *apexBundle) EnableSanitizer(sanitizerName string) { 563 if !android.InList(sanitizerName, a.properties.SanitizerNames) { 564 a.properties.SanitizerNames = append(a.properties.SanitizerNames, sanitizerName) 565 } 566} 567 568func (a *apexBundle) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool { 569 if android.InList(sanitizerName, a.properties.SanitizerNames) { 570 return true 571 } 572 573 // Then follow the global setting 574 globalSanitizerNames := []string{} 575 if a.Host() { 576 globalSanitizerNames = ctx.Config().SanitizeHost() 577 } else { 578 arches := ctx.Config().SanitizeDeviceArch() 579 if len(arches) == 0 || android.InList(a.Arch().ArchType.Name, arches) { 580 globalSanitizerNames = ctx.Config().SanitizeDevice() 581 } 582 } 583 return android.InList(sanitizerName, globalSanitizerNames) 584} 585 586func getCopyManifestForNativeLibrary(cc *cc.Module, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) { 587 // Decide the APEX-local directory by the multilib of the library 588 // In the future, we may query this to the module. 589 switch cc.Arch().ArchType.Multilib { 590 case "lib32": 591 dirInApex = "lib" 592 case "lib64": 593 dirInApex = "lib64" 594 } 595 dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath()) 596 if !cc.Arch().Native { 597 dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String()) 598 } 599 if handleSpecialLibs { 600 switch cc.Name() { 601 case "libc", "libm", "libdl": 602 // Special case for bionic libs. This is to prevent the bionic libs 603 // from being included in the search path /apex/com.android.apex/lib. 604 // This exclusion is required because bionic libs in the runtime APEX 605 // are available via the legacy paths /system/lib/libc.so, etc. By the 606 // init process, the bionic libs in the APEX are bind-mounted to the 607 // legacy paths and thus will be loaded into the default linker namespace. 608 // If the bionic libs are directly in /apex/com.android.apex/lib then 609 // the same libs will be again loaded to the runtime linker namespace, 610 // which will result double loading of bionic libs that isn't supported. 611 dirInApex = filepath.Join(dirInApex, "bionic") 612 } 613 } 614 615 fileToCopy = cc.OutputFile().Path() 616 return 617} 618 619func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirInApex string) { 620 dirInApex = filepath.Join("bin", cc.RelativeInstallPath()) 621 fileToCopy = cc.OutputFile().Path() 622 return 623} 624 625func getCopyManifestForPyBinary(py *python.Module) (fileToCopy android.Path, dirInApex string) { 626 dirInApex = "bin" 627 fileToCopy = py.HostToolPath().Path() 628 return 629} 630func getCopyManifestForGoBinary(ctx android.ModuleContext, gb bootstrap.GoBinaryTool) (fileToCopy android.Path, dirInApex string) { 631 dirInApex = "bin" 632 s, err := filepath.Rel(android.PathForOutput(ctx).String(), gb.InstallPath()) 633 if err != nil { 634 ctx.ModuleErrorf("Unable to use compiled binary at %s", gb.InstallPath()) 635 return 636 } 637 fileToCopy = android.PathForOutput(ctx, s) 638 return 639} 640 641func getCopyManifestForShBinary(sh *android.ShBinary) (fileToCopy android.Path, dirInApex string) { 642 dirInApex = filepath.Join("bin", sh.SubDir()) 643 fileToCopy = sh.OutputFile() 644 return 645} 646 647func getCopyManifestForJavaLibrary(java *java.Library) (fileToCopy android.Path, dirInApex string) { 648 dirInApex = "javalib" 649 fileToCopy = java.DexJarFile() 650 return 651} 652 653func getCopyManifestForPrebuiltEtc(prebuilt *android.PrebuiltEtc) (fileToCopy android.Path, dirInApex string) { 654 dirInApex = filepath.Join("etc", prebuilt.SubDir()) 655 fileToCopy = prebuilt.OutputFile() 656 return 657} 658 659func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { 660 filesInfo := []apexFile{} 661 662 if a.properties.Payload_type == nil || *a.properties.Payload_type == "image" { 663 a.apexTypes = imageApex 664 } else if *a.properties.Payload_type == "zip" { 665 a.apexTypes = zipApex 666 } else if *a.properties.Payload_type == "both" { 667 a.apexTypes = both 668 } else { 669 ctx.PropertyErrorf("type", "%q is not one of \"image\", \"zip\", or \"both\".", *a.properties.Payload_type) 670 return 671 } 672 673 handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case) 674 675 ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { 676 if _, ok := parent.(*apexBundle); ok { 677 // direct dependencies 678 depTag := ctx.OtherModuleDependencyTag(child) 679 depName := ctx.OtherModuleName(child) 680 switch depTag { 681 case sharedLibTag: 682 if cc, ok := child.(*cc.Module); ok { 683 fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs) 684 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil}) 685 return true 686 } else { 687 ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName) 688 } 689 case executableTag: 690 if cc, ok := child.(*cc.Module); ok { 691 if !cc.Arch().Native { 692 // There is only one 'bin' directory so we shouldn't bother copying in 693 // native-bridge'd binaries and only use main ones. 694 return true 695 } 696 fileToCopy, dirInApex := getCopyManifestForExecutable(cc) 697 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeExecutable, cc, cc.Symlinks()}) 698 return true 699 } else if sh, ok := child.(*android.ShBinary); ok { 700 fileToCopy, dirInApex := getCopyManifestForShBinary(sh) 701 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, shBinary, sh, nil}) 702 } else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() { 703 fileToCopy, dirInApex := getCopyManifestForPyBinary(py) 704 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, pyBinary, py, nil}) 705 } else if gb, ok := child.(bootstrap.GoBinaryTool); ok && a.Host() { 706 fileToCopy, dirInApex := getCopyManifestForGoBinary(ctx, gb) 707 // NB: Since go binaries are static we don't need the module for anything here, which is 708 // good since the go tool is a blueprint.Module not an android.Module like we would 709 // normally use. 710 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, goBinary, nil, nil}) 711 } else { 712 ctx.PropertyErrorf("binaries", "%q is neither cc_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName) 713 } 714 case javaLibTag: 715 if java, ok := child.(*java.Library); ok { 716 fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java) 717 if fileToCopy == nil { 718 ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) 719 } else { 720 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, javaSharedLib, java, nil}) 721 } 722 return true 723 } else { 724 ctx.PropertyErrorf("java_libs", "%q is not a java_library module", depName) 725 } 726 case prebuiltTag: 727 if prebuilt, ok := child.(*android.PrebuiltEtc); ok { 728 fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt) 729 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, etc, prebuilt, nil}) 730 return true 731 } else { 732 ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName) 733 } 734 case keyTag: 735 if key, ok := child.(*apexKey); ok { 736 a.private_key_file = key.private_key_file 737 a.public_key_file = key.public_key_file 738 return false 739 } else { 740 ctx.PropertyErrorf("key", "%q is not an apex_key module", depName) 741 } 742 case certificateTag: 743 if dep, ok := child.(*java.AndroidAppCertificate); ok { 744 a.container_certificate_file = dep.Certificate.Pem 745 a.container_private_key_file = dep.Certificate.Key 746 return false 747 } else { 748 ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName) 749 } 750 } 751 } else { 752 // indirect dependencies 753 if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() { 754 if cc, ok := child.(*cc.Module); ok { 755 if !a.Host() && (cc.IsStubs() || cc.HasStubsVariants()) { 756 // If the dependency is a stubs lib, don't include it in this APEX, 757 // but make sure that the lib is installed on the device. 758 // In case no APEX is having the lib, the lib is installed to the system 759 // partition. 760 // 761 // Always include if we are a host-apex however since those won't have any 762 // system libraries. 763 if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.externalDeps) { 764 a.externalDeps = append(a.externalDeps, cc.Name()) 765 } 766 // Don't track further 767 return false 768 } 769 depName := ctx.OtherModuleName(child) 770 fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs) 771 filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil}) 772 return true 773 } 774 } 775 } 776 return false 777 }) 778 779 a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() 780 if a.private_key_file == nil { 781 ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key)) 782 return 783 } 784 785 // remove duplicates in filesInfo 786 removeDup := func(filesInfo []apexFile) []apexFile { 787 encountered := make(map[android.Path]bool) 788 result := []apexFile{} 789 for _, f := range filesInfo { 790 if !encountered[f.builtFile] { 791 encountered[f.builtFile] = true 792 result = append(result, f) 793 } 794 } 795 return result 796 } 797 filesInfo = removeDup(filesInfo) 798 799 // to have consistent build rules 800 sort.Slice(filesInfo, func(i, j int) bool { 801 return filesInfo[i].builtFile.String() < filesInfo[j].builtFile.String() 802 }) 803 804 // prepend the name of this APEX to the module names. These names will be the names of 805 // modules that will be defined if the APEX is flattened. 806 for i := range filesInfo { 807 filesInfo[i].moduleName = ctx.ModuleName() + "." + filesInfo[i].moduleName 808 } 809 810 a.installDir = android.PathForModuleInstall(ctx, "apex") 811 a.filesInfo = filesInfo 812 813 if a.apexTypes.zip() { 814 a.buildUnflattenedApex(ctx, zipApex) 815 } 816 if a.apexTypes.image() { 817 // Build rule for unflattened APEX is created even when ctx.Config().FlattenApex() 818 // is true. This is to support referencing APEX via ":<module_name" syntax 819 // in other modules. It is in AndroidMk where the selection of flattened 820 // or unflattened APEX is made. 821 a.buildUnflattenedApex(ctx, imageApex) 822 a.buildFlattenedApex(ctx) 823 } 824} 825 826func (a *apexBundle) buildNoticeFile(ctx android.ModuleContext, apexFileName string) android.OptionalPath { 827 noticeFiles := []android.Path{} 828 for _, f := range a.filesInfo { 829 if f.module != nil { 830 notice := f.module.NoticeFile() 831 if notice.Valid() { 832 noticeFiles = append(noticeFiles, notice.Path()) 833 } 834 } 835 } 836 // append the notice file specified in the apex module itself 837 if a.NoticeFile().Valid() { 838 noticeFiles = append(noticeFiles, a.NoticeFile().Path()) 839 } 840 841 if len(noticeFiles) == 0 { 842 return android.OptionalPath{} 843 } 844 845 return android.OptionalPathForPath( 846 android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles))) 847} 848 849func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, apexType apexPackaging) { 850 cert := String(a.properties.Certificate) 851 if cert != "" && android.SrcIsModule(cert) == "" { 852 defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) 853 a.container_certificate_file = defaultDir.Join(ctx, cert+".x509.pem") 854 a.container_private_key_file = defaultDir.Join(ctx, cert+".pk8") 855 } else if cert == "" { 856 pem, key := ctx.Config().DefaultAppCertificate(ctx) 857 a.container_certificate_file = pem 858 a.container_private_key_file = key 859 } 860 861 manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")) 862 863 var abis []string 864 for _, target := range ctx.MultiTargets() { 865 if len(target.Arch.Abi) > 0 { 866 abis = append(abis, target.Arch.Abi[0]) 867 } 868 } 869 870 abis = android.FirstUniqueStrings(abis) 871 872 suffix := apexType.suffix() 873 unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+".unsigned") 874 875 filesToCopy := []android.Path{} 876 for _, f := range a.filesInfo { 877 filesToCopy = append(filesToCopy, f.builtFile) 878 } 879 880 copyCommands := []string{} 881 for i, src := range filesToCopy { 882 dest := filepath.Join(a.filesInfo[i].installDir, src.Base()) 883 dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest) 884 copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path)) 885 copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path) 886 for _, sym := range a.filesInfo[i].symlinks { 887 symlinkDest := filepath.Join(filepath.Dir(dest_path), sym) 888 copyCommands = append(copyCommands, "ln -s "+filepath.Base(dest)+" "+symlinkDest) 889 } 890 } 891 implicitInputs := append(android.Paths(nil), filesToCopy...) 892 implicitInputs = append(implicitInputs, manifest) 893 894 outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String() 895 prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") 896 897 if apexType.image() { 898 // files and dirs that will be created in APEX 899 var readOnlyPaths []string 900 var executablePaths []string // this also includes dirs 901 for _, f := range a.filesInfo { 902 pathInApex := filepath.Join(f.installDir, f.builtFile.Base()) 903 if f.installDir == "bin" { 904 executablePaths = append(executablePaths, pathInApex) 905 for _, s := range f.symlinks { 906 executablePaths = append(executablePaths, filepath.Join("bin", s)) 907 } 908 } else { 909 readOnlyPaths = append(readOnlyPaths, pathInApex) 910 } 911 dir := f.installDir 912 for !android.InList(dir, executablePaths) && dir != "" { 913 executablePaths = append(executablePaths, dir) 914 dir, _ = filepath.Split(dir) // move up to the parent 915 if len(dir) > 0 { 916 // remove trailing slash 917 dir = dir[:len(dir)-1] 918 } 919 } 920 } 921 sort.Strings(readOnlyPaths) 922 sort.Strings(executablePaths) 923 cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config") 924 ctx.Build(pctx, android.BuildParams{ 925 Rule: generateFsConfig, 926 Output: cannedFsConfig, 927 Description: "generate fs config", 928 Args: map[string]string{ 929 "ro_paths": strings.Join(readOnlyPaths, " "), 930 "exec_paths": strings.Join(executablePaths, " "), 931 }, 932 }) 933 934 fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName()) 935 fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts" 936 fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath) 937 if !fileContextsOptionalPath.Valid() { 938 ctx.ModuleErrorf("Cannot find file_contexts file: %q", fileContextsPath) 939 return 940 } 941 fileContexts := fileContextsOptionalPath.Path() 942 943 optFlags := []string{} 944 945 // Additional implicit inputs. 946 implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, a.private_key_file, a.public_key_file) 947 optFlags = append(optFlags, "--pubkey "+a.public_key_file.String()) 948 949 manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName()) 950 if overridden { 951 optFlags = append(optFlags, "--override_apk_package_name "+manifestPackageName) 952 } 953 954 if a.properties.AndroidManifest != nil { 955 androidManifestFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.AndroidManifest)) 956 implicitInputs = append(implicitInputs, androidManifestFile) 957 optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String()) 958 } 959 960 targetSdkVersion := ctx.Config().DefaultAppTargetSdk() 961 if targetSdkVersion == ctx.Config().PlatformSdkCodename() && 962 ctx.Config().UnbundledBuild() && 963 !ctx.Config().UnbundledBuildUsePrebuiltSdks() && 964 ctx.Config().IsEnvTrue("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT") { 965 apiFingerprint := java.ApiFingerprintPath(ctx) 966 targetSdkVersion += fmt.Sprintf(".$$(cat %s)", apiFingerprint.String()) 967 implicitInputs = append(implicitInputs, apiFingerprint) 968 } 969 optFlags = append(optFlags, "--target_sdk_version "+targetSdkVersion) 970 971 noticeFile := a.buildNoticeFile(ctx, ctx.ModuleName()+suffix) 972 if noticeFile.Valid() { 973 // If there's a NOTICE file, embed it as an asset file in the APEX. 974 implicitInputs = append(implicitInputs, noticeFile.Path()) 975 optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeFile.String())) 976 } 977 978 ctx.Build(pctx, android.BuildParams{ 979 Rule: apexRule, 980 Implicits: implicitInputs, 981 Output: unsignedOutputFile, 982 Description: "apex (" + apexType.name() + ")", 983 Args: map[string]string{ 984 "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, 985 "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(), 986 "copy_commands": strings.Join(copyCommands, " && "), 987 "manifest": manifest.String(), 988 "file_contexts": fileContexts.String(), 989 "canned_fs_config": cannedFsConfig.String(), 990 "key": a.private_key_file.String(), 991 "opt_flags": strings.Join(optFlags, " "), 992 }, 993 }) 994 995 apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+suffix) 996 bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+"-base.zip") 997 a.bundleModuleFile = bundleModuleFile 998 999 ctx.Build(pctx, android.BuildParams{ 1000 Rule: apexProtoConvertRule, 1001 Input: unsignedOutputFile, 1002 Output: apexProtoFile, 1003 Description: "apex proto convert", 1004 }) 1005 1006 ctx.Build(pctx, android.BuildParams{ 1007 Rule: apexBundleRule, 1008 Input: apexProtoFile, 1009 Output: a.bundleModuleFile, 1010 Description: "apex bundle module", 1011 Args: map[string]string{ 1012 "abi": strings.Join(abis, "."), 1013 }, 1014 }) 1015 } else { 1016 ctx.Build(pctx, android.BuildParams{ 1017 Rule: zipApexRule, 1018 Implicits: implicitInputs, 1019 Output: unsignedOutputFile, 1020 Description: "apex (" + apexType.name() + ")", 1021 Args: map[string]string{ 1022 "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, 1023 "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(), 1024 "copy_commands": strings.Join(copyCommands, " && "), 1025 "manifest": manifest.String(), 1026 }, 1027 }) 1028 } 1029 1030 a.outputFiles[apexType] = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix) 1031 ctx.Build(pctx, android.BuildParams{ 1032 Rule: java.Signapk, 1033 Description: "signapk", 1034 Output: a.outputFiles[apexType], 1035 Input: unsignedOutputFile, 1036 Args: map[string]string{ 1037 "certificates": a.container_certificate_file.String() + " " + a.container_private_key_file.String(), 1038 "flags": "-a 4096", //alignment 1039 }, 1040 }) 1041 1042 // Install to $OUT/soong/{target,host}/.../apex 1043 if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) { 1044 ctx.InstallFile(a.installDir, ctx.ModuleName()+suffix, a.outputFiles[apexType]) 1045 } 1046} 1047 1048func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) { 1049 if a.installable() { 1050 // For flattened APEX, do nothing but make sure that apex_manifest.json and apex_pubkey are also copied along 1051 // with other ordinary files. 1052 manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")) 1053 1054 // rename to apex_manifest.json 1055 copiedManifest := android.PathForModuleOut(ctx, "apex_manifest.json") 1056 ctx.Build(pctx, android.BuildParams{ 1057 Rule: android.Cp, 1058 Input: manifest, 1059 Output: copiedManifest, 1060 }) 1061 a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", ".", etc, nil, nil}) 1062 1063 // rename to apex_pubkey 1064 copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey") 1065 ctx.Build(pctx, android.BuildParams{ 1066 Rule: android.Cp, 1067 Input: a.public_key_file, 1068 Output: copiedPubkey, 1069 }) 1070 a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, ctx.ModuleName() + ".apex_pubkey", ".", etc, nil, nil}) 1071 1072 if ctx.Config().FlattenApex() { 1073 for _, fi := range a.filesInfo { 1074 dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir) 1075 target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile) 1076 for _, sym := range fi.symlinks { 1077 ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target) 1078 } 1079 } 1080 } 1081 } 1082} 1083 1084func (a *apexBundle) AndroidMk() android.AndroidMkData { 1085 writers := []android.AndroidMkData{} 1086 if a.apexTypes.image() { 1087 writers = append(writers, a.androidMkForType(imageApex)) 1088 } 1089 if a.apexTypes.zip() { 1090 writers = append(writers, a.androidMkForType(zipApex)) 1091 } 1092 return android.AndroidMkData{ 1093 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { 1094 for _, data := range writers { 1095 data.Custom(w, name, prefix, moduleDir, data) 1096 } 1097 }} 1098} 1099 1100func (a *apexBundle) androidMkForFiles(w io.Writer, name, moduleDir string, apexType apexPackaging) []string { 1101 moduleNames := []string{} 1102 1103 for _, fi := range a.filesInfo { 1104 if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake { 1105 continue 1106 } 1107 if !android.InList(fi.moduleName, moduleNames) { 1108 moduleNames = append(moduleNames, fi.moduleName) 1109 } 1110 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") 1111 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) 1112 fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName) 1113 // /apex/<name>/{lib|framework|...} 1114 pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", 1115 proptools.StringDefault(a.properties.Apex_name, name), fi.installDir) 1116 if a.flattened && apexType.image() { 1117 // /system/apex/<name>/{lib|framework|...} 1118 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", 1119 a.installDir.RelPathString(), name, fi.installDir)) 1120 fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated) 1121 if len(fi.symlinks) > 0 { 1122 fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " ")) 1123 } 1124 1125 if fi.module != nil && fi.module.NoticeFile().Valid() { 1126 fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", fi.module.NoticeFile().Path().String()) 1127 } 1128 } else { 1129 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated) 1130 } 1131 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String()) 1132 fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.NameInMake()) 1133 if fi.module != nil { 1134 archStr := fi.module.Target().Arch.ArchType.String() 1135 host := false 1136 switch fi.module.Target().Os.Class { 1137 case android.Host: 1138 if archStr != "common" { 1139 fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr) 1140 } 1141 host = true 1142 case android.HostCross: 1143 if archStr != "common" { 1144 fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr) 1145 } 1146 host = true 1147 case android.Device: 1148 if archStr != "common" { 1149 fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr) 1150 } 1151 } 1152 if host { 1153 makeOs := fi.module.Target().Os.String() 1154 if fi.module.Target().Os == android.Linux || fi.module.Target().Os == android.LinuxBionic { 1155 makeOs = "linux" 1156 } 1157 fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", makeOs) 1158 fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true") 1159 } 1160 } 1161 if fi.class == javaSharedLib { 1162 javaModule := fi.module.(*java.Library) 1163 // soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore 1164 // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise 1165 // we will have foo.jar.jar 1166 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".jar")) 1167 fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String()) 1168 fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String()) 1169 fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String()) 1170 fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false") 1171 fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk") 1172 } else if fi.class == nativeSharedLib || fi.class == nativeExecutable { 1173 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base()) 1174 if cc, ok := fi.module.(*cc.Module); ok && cc.UnstrippedOutputFile() != nil { 1175 fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String()) 1176 } 1177 fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk") 1178 } else { 1179 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base()) 1180 fmt.Fprintln(w, "include $(BUILD_PREBUILT)") 1181 } 1182 } 1183 return moduleNames 1184} 1185 1186func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData { 1187 return android.AndroidMkData{ 1188 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { 1189 moduleNames := []string{} 1190 if a.installable() { 1191 moduleNames = a.androidMkForFiles(w, name, moduleDir, apexType) 1192 } 1193 1194 if a.flattened && apexType.image() { 1195 // Only image APEXes can be flattened. 1196 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") 1197 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) 1198 fmt.Fprintln(w, "LOCAL_MODULE :=", name) 1199 if len(moduleNames) > 0 { 1200 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " ")) 1201 } 1202 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)") 1203 } else { 1204 // zip-apex is the less common type so have the name refer to the image-apex 1205 // only and use {name}.zip if you want the zip-apex 1206 if apexType == zipApex && a.apexTypes == both { 1207 name = name + ".zip" 1208 } 1209 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") 1210 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) 1211 fmt.Fprintln(w, "LOCAL_MODULE :=", name) 1212 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class? 1213 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFiles[apexType].String()) 1214 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString())) 1215 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix()) 1216 fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable()) 1217 if len(moduleNames) > 0 { 1218 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " ")) 1219 } 1220 if len(a.externalDeps) > 0 { 1221 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.externalDeps, " ")) 1222 } 1223 fmt.Fprintln(w, "include $(BUILD_PREBUILT)") 1224 1225 if apexType == imageApex { 1226 fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String()) 1227 } 1228 } 1229 }} 1230} 1231 1232func testApexBundleFactory() android.Module { 1233 return ApexBundleFactory( /*testApex*/ true) 1234} 1235 1236func apexBundleFactory() android.Module { 1237 return ApexBundleFactory( /*testApex*/ false) 1238} 1239 1240func ApexBundleFactory(testApex bool) android.Module { 1241 module := &apexBundle{ 1242 outputFiles: map[apexPackaging]android.WritablePath{}, 1243 testApex: testApex, 1244 } 1245 module.AddProperties(&module.properties) 1246 module.AddProperties(&module.targetProperties) 1247 module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool { 1248 return class == android.Device && ctx.Config().DevicePrefer32BitExecutables() 1249 }) 1250 android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 1251 android.InitDefaultableModule(module) 1252 return module 1253} 1254 1255// 1256// Defaults 1257// 1258type Defaults struct { 1259 android.ModuleBase 1260 android.DefaultsModuleBase 1261} 1262 1263func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1264} 1265 1266func defaultsFactory() android.Module { 1267 return DefaultsFactory() 1268} 1269 1270func DefaultsFactory(props ...interface{}) android.Module { 1271 module := &Defaults{} 1272 1273 module.AddProperties(props...) 1274 module.AddProperties( 1275 &apexBundleProperties{}, 1276 &apexTargetBundleProperties{}, 1277 ) 1278 1279 android.InitDefaultsModule(module) 1280 return module 1281} 1282 1283// 1284// Prebuilt APEX 1285// 1286type Prebuilt struct { 1287 android.ModuleBase 1288 prebuilt android.Prebuilt 1289 1290 properties PrebuiltProperties 1291 1292 inputApex android.Path 1293 installDir android.OutputPath 1294 installFilename string 1295 outputApex android.WritablePath 1296} 1297 1298type PrebuiltProperties struct { 1299 // the path to the prebuilt .apex file to import. 1300 Source string `blueprint:"mutated"` 1301 ForceDisable bool `blueprint:"mutated"` 1302 1303 Src *string 1304 Arch struct { 1305 Arm struct { 1306 Src *string 1307 } 1308 Arm64 struct { 1309 Src *string 1310 } 1311 X86 struct { 1312 Src *string 1313 } 1314 X86_64 struct { 1315 Src *string 1316 } 1317 } 1318 1319 Installable *bool 1320 // Optional name for the installed apex. If unspecified, name of the 1321 // module is used as the file name 1322 Filename *string 1323} 1324 1325func (p *Prebuilt) installable() bool { 1326 return p.properties.Installable == nil || proptools.Bool(p.properties.Installable) 1327} 1328 1329func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) { 1330 // If the device is configured to use flattened APEX, force disable the prebuilt because 1331 // the prebuilt is a non-flattened one. 1332 forceDisable := ctx.Config().FlattenApex() 1333 1334 // Force disable the prebuilts when we are doing unbundled build. We do unbundled build 1335 // to build the prebuilts themselves. 1336 forceDisable = forceDisable || ctx.Config().UnbundledBuild() 1337 1338 // b/137216042 don't use prebuilts when address sanitizer is on 1339 forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) || 1340 android.InList("hwaddress", ctx.Config().SanitizeDevice()) 1341 1342 if forceDisable && p.prebuilt.SourceExists() { 1343 p.properties.ForceDisable = true 1344 return 1345 } 1346 1347 // This is called before prebuilt_select and prebuilt_postdeps mutators 1348 // The mutators requires that src to be set correctly for each arch so that 1349 // arch variants are disabled when src is not provided for the arch. 1350 if len(ctx.MultiTargets()) != 1 { 1351 ctx.ModuleErrorf("compile_multilib shouldn't be \"both\" for prebuilt_apex") 1352 return 1353 } 1354 var src string 1355 switch ctx.MultiTargets()[0].Arch.ArchType { 1356 case android.Arm: 1357 src = String(p.properties.Arch.Arm.Src) 1358 case android.Arm64: 1359 src = String(p.properties.Arch.Arm64.Src) 1360 case android.X86: 1361 src = String(p.properties.Arch.X86.Src) 1362 case android.X86_64: 1363 src = String(p.properties.Arch.X86_64.Src) 1364 default: 1365 ctx.ModuleErrorf("prebuilt_apex does not support %q", ctx.MultiTargets()[0].Arch.String()) 1366 return 1367 } 1368 if src == "" { 1369 src = String(p.properties.Src) 1370 } 1371 p.properties.Source = src 1372} 1373 1374func (p *Prebuilt) Srcs() android.Paths { 1375 return android.Paths{p.outputApex} 1376} 1377 1378func (p *Prebuilt) InstallFilename() string { 1379 return proptools.StringDefault(p.properties.Filename, p.BaseModuleName()+imageApexSuffix) 1380} 1381 1382func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1383 if p.properties.ForceDisable { 1384 return 1385 } 1386 1387 // TODO(jungjw): Check the key validity. 1388 p.inputApex = p.Prebuilt().SingleSourcePath(ctx) 1389 p.installDir = android.PathForModuleInstall(ctx, "apex") 1390 p.installFilename = p.InstallFilename() 1391 if !strings.HasSuffix(p.installFilename, imageApexSuffix) { 1392 ctx.ModuleErrorf("filename should end in %s for prebuilt_apex", imageApexSuffix) 1393 } 1394 p.outputApex = android.PathForModuleOut(ctx, p.installFilename) 1395 ctx.Build(pctx, android.BuildParams{ 1396 Rule: android.Cp, 1397 Input: p.inputApex, 1398 Output: p.outputApex, 1399 }) 1400 if p.installable() { 1401 ctx.InstallFile(p.installDir, p.installFilename, p.inputApex) 1402 } 1403} 1404 1405func (p *Prebuilt) Prebuilt() *android.Prebuilt { 1406 return &p.prebuilt 1407} 1408 1409func (p *Prebuilt) Name() string { 1410 return p.prebuilt.Name(p.ModuleBase.Name()) 1411} 1412 1413func (p *Prebuilt) AndroidMk() android.AndroidMkData { 1414 return android.AndroidMkData{ 1415 Class: "ETC", 1416 OutputFile: android.OptionalPathForPath(p.inputApex), 1417 Include: "$(BUILD_PREBUILT)", 1418 Extra: []android.AndroidMkExtraFunc{ 1419 func(w io.Writer, outputFile android.Path) { 1420 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", p.installDir.RelPathString())) 1421 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", p.installFilename) 1422 fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.installable()) 1423 }, 1424 }, 1425 } 1426} 1427 1428// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. 1429func PrebuiltFactory() android.Module { 1430 module := &Prebuilt{} 1431 module.AddProperties(&module.properties) 1432 android.InitSingleSourcePrebuiltModule(module, &module.properties.Source) 1433 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 1434 return module 1435} 1436