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 android 16 17// This is the primary location to write and read all configuration values and 18// product variables necessary for soong_build's operation. 19 20import ( 21 "encoding/json" 22 "errors" 23 "fmt" 24 "io/ioutil" 25 "os" 26 "path/filepath" 27 "reflect" 28 "runtime" 29 "strconv" 30 "strings" 31 "sync" 32 33 "github.com/google/blueprint" 34 "github.com/google/blueprint/bootstrap" 35 "github.com/google/blueprint/pathtools" 36 "github.com/google/blueprint/proptools" 37 38 "android/soong/android/soongconfig" 39 "android/soong/bazel" 40 "android/soong/remoteexec" 41 "android/soong/starlark_fmt" 42) 43 44// Bool re-exports proptools.Bool for the android package. 45var Bool = proptools.Bool 46 47// String re-exports proptools.String for the android package. 48var String = proptools.String 49 50// StringDefault re-exports proptools.StringDefault for the android package. 51var StringDefault = proptools.StringDefault 52 53// FutureApiLevelInt is a placeholder constant for unreleased API levels. 54const FutureApiLevelInt = 10000 55 56// FutureApiLevel represents unreleased API levels. 57var FutureApiLevel = ApiLevel{ 58 value: "current", 59 number: FutureApiLevelInt, 60 isPreview: true, 61} 62 63// The product variables file name, containing product config from Kati. 64const productVariablesFileName = "soong.variables" 65 66// A Config object represents the entire build configuration for Android. 67type Config struct { 68 *config 69} 70 71// SoongOutDir returns the build output directory for the configuration. 72func (c Config) SoongOutDir() string { 73 return c.soongOutDir 74} 75 76func (c Config) OutDir() string { 77 return c.outDir 78} 79 80func (c Config) RunGoTests() bool { 81 return c.runGoTests 82} 83 84func (c Config) DebugCompilation() bool { 85 return false // Never compile Go code in the main build for debugging 86} 87 88func (c Config) Subninjas() []string { 89 return []string{} 90} 91 92func (c Config) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderInvocation { 93 return []bootstrap.PrimaryBuilderInvocation{} 94} 95 96// A DeviceConfig object represents the configuration for a particular device 97// being built. For now there will only be one of these, but in the future there 98// may be multiple devices being built. 99type DeviceConfig struct { 100 *deviceConfig 101} 102 103// VendorConfig represents the configuration for vendor-specific behavior. 104type VendorConfig soongconfig.SoongConfig 105 106// Definition of general build configuration for soong_build. Some of these 107// product configuration values are read from Kati-generated soong.variables. 108type config struct { 109 // Options configurable with soong.variables 110 productVariables productVariables 111 112 // Only available on configs created by TestConfig 113 TestProductVariables *productVariables 114 115 // A specialized context object for Bazel/Soong mixed builds and migration 116 // purposes. 117 BazelContext BazelContext 118 119 ProductVariablesFileName string 120 121 // BuildOS stores the OsType for the OS that the build is running on. 122 BuildOS OsType 123 124 // BuildArch stores the ArchType for the CPU that the build is running on. 125 BuildArch ArchType 126 127 Targets map[OsType][]Target 128 BuildOSTarget Target // the Target for tools run on the build machine 129 BuildOSCommonTarget Target // the Target for common (java) tools run on the build machine 130 AndroidCommonTarget Target // the Target for common modules for the Android device 131 AndroidFirstDeviceTarget Target // the first Target for modules for the Android device 132 133 // multilibConflicts for an ArchType is true if there is earlier configured 134 // device architecture with the same multilib value. 135 multilibConflicts map[ArchType]bool 136 137 deviceConfig *deviceConfig 138 139 outDir string // The output directory (usually out/) 140 soongOutDir string 141 moduleListFile string // the path to the file which lists blueprint files to parse. 142 143 runGoTests bool 144 145 env map[string]string 146 envLock sync.Mutex 147 envDeps map[string]string 148 envFrozen bool 149 150 // Changes behavior based on whether Kati runs after soong_build, or if soong_build 151 // runs standalone. 152 katiEnabled bool 153 154 captureBuild bool // true for tests, saves build parameters for each module 155 ignoreEnvironment bool // true for tests, returns empty from all Getenv calls 156 157 fs pathtools.FileSystem 158 mockBpList string 159 160 runningAsBp2Build bool 161 bp2buildPackageConfig bp2BuildConversionAllowlist 162 Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions 163 164 // If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error 165 // in tests when a path doesn't exist. 166 TestAllowNonExistentPaths bool 167 168 // The list of files that when changed, must invalidate soong_build to 169 // regenerate build.ninja. 170 ninjaFileDepsSet sync.Map 171 172 OncePer 173} 174 175type deviceConfig struct { 176 config *config 177 OncePer 178} 179 180type jsonConfigurable interface { 181 SetDefaultConfig() 182} 183 184func loadConfig(config *config) error { 185 return loadFromConfigFile(&config.productVariables, absolutePath(config.ProductVariablesFileName)) 186} 187 188// loadFromConfigFile loads and decodes configuration options from a JSON file 189// in the current working directory. 190func loadFromConfigFile(configurable *productVariables, filename string) error { 191 // Try to open the file 192 configFileReader, err := os.Open(filename) 193 defer configFileReader.Close() 194 if os.IsNotExist(err) { 195 // Need to create a file, so that blueprint & ninja don't get in 196 // a dependency tracking loop. 197 // Make a file-configurable-options with defaults, write it out using 198 // a json writer. 199 configurable.SetDefaultConfig() 200 err = saveToConfigFile(configurable, filename) 201 if err != nil { 202 return err 203 } 204 } else if err != nil { 205 return fmt.Errorf("config file: could not open %s: %s", filename, err.Error()) 206 } else { 207 // Make a decoder for it 208 jsonDecoder := json.NewDecoder(configFileReader) 209 err = jsonDecoder.Decode(configurable) 210 if err != nil { 211 return fmt.Errorf("config file: %s did not parse correctly: %s", filename, err.Error()) 212 } 213 } 214 215 if Bool(configurable.GcovCoverage) && Bool(configurable.ClangCoverage) { 216 return fmt.Errorf("GcovCoverage and ClangCoverage cannot both be set") 217 } 218 219 configurable.Native_coverage = proptools.BoolPtr( 220 Bool(configurable.GcovCoverage) || 221 Bool(configurable.ClangCoverage)) 222 223 // when Platform_sdk_final is true (or PLATFORM_VERSION_CODENAME is REL), use Platform_sdk_version; 224 // if false (pre-released version, for example), use Platform_sdk_codename. 225 if Bool(configurable.Platform_sdk_final) { 226 if configurable.Platform_sdk_version != nil { 227 configurable.Platform_sdk_version_or_codename = 228 proptools.StringPtr(strconv.Itoa(*(configurable.Platform_sdk_version))) 229 } else { 230 return fmt.Errorf("Platform_sdk_version cannot be pointed by a NULL pointer") 231 } 232 } else { 233 configurable.Platform_sdk_version_or_codename = 234 proptools.StringPtr(String(configurable.Platform_sdk_codename)) 235 } 236 237 return saveToBazelConfigFile(configurable, filepath.Dir(filename)) 238} 239 240// atomically writes the config file in case two copies of soong_build are running simultaneously 241// (for example, docs generation and ninja manifest generation) 242func saveToConfigFile(config *productVariables, filename string) error { 243 data, err := json.MarshalIndent(&config, "", " ") 244 if err != nil { 245 return fmt.Errorf("cannot marshal config data: %s", err.Error()) 246 } 247 248 f, err := ioutil.TempFile(filepath.Dir(filename), "config") 249 if err != nil { 250 return fmt.Errorf("cannot create empty config file %s: %s", filename, err.Error()) 251 } 252 defer os.Remove(f.Name()) 253 defer f.Close() 254 255 _, err = f.Write(data) 256 if err != nil { 257 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error()) 258 } 259 260 _, err = f.WriteString("\n") 261 if err != nil { 262 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error()) 263 } 264 265 f.Close() 266 os.Rename(f.Name(), filename) 267 268 return nil 269} 270 271func saveToBazelConfigFile(config *productVariables, outDir string) error { 272 dir := filepath.Join(outDir, bazel.SoongInjectionDirName, "product_config") 273 err := createDirIfNonexistent(dir, os.ModePerm) 274 if err != nil { 275 return fmt.Errorf("Could not create dir %s: %s", dir, err) 276 } 277 278 nonArchVariantProductVariables := []string{} 279 archVariantProductVariables := []string{} 280 p := variableProperties{} 281 t := reflect.TypeOf(p.Product_variables) 282 for i := 0; i < t.NumField(); i++ { 283 f := t.Field(i) 284 nonArchVariantProductVariables = append(nonArchVariantProductVariables, strings.ToLower(f.Name)) 285 if proptools.HasTag(f, "android", "arch_variant") { 286 archVariantProductVariables = append(archVariantProductVariables, strings.ToLower(f.Name)) 287 } 288 } 289 290 nonArchVariantProductVariablesJson := starlark_fmt.PrintStringList(nonArchVariantProductVariables, 0) 291 if err != nil { 292 return fmt.Errorf("cannot marshal product variable data: %s", err.Error()) 293 } 294 295 archVariantProductVariablesJson := starlark_fmt.PrintStringList(archVariantProductVariables, 0) 296 if err != nil { 297 return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error()) 298 } 299 300 configJson, err := json.MarshalIndent(&config, "", " ") 301 if err != nil { 302 return fmt.Errorf("cannot marshal config data: %s", err.Error()) 303 } 304 305 bzl := []string{ 306 bazel.GeneratedBazelFileWarning, 307 fmt.Sprintf(`_product_vars = json.decode("""%s""")`, configJson), 308 fmt.Sprintf(`_product_var_constraints = %s`, nonArchVariantProductVariablesJson), 309 fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson), 310 "\n", ` 311product_vars = _product_vars 312product_var_constraints = _product_var_constraints 313arch_variant_product_var_constraints = _arch_variant_product_var_constraints 314`, 315 } 316 err = ioutil.WriteFile(filepath.Join(dir, "product_variables.bzl"), []byte(strings.Join(bzl, "\n")), 0644) 317 if err != nil { 318 return fmt.Errorf("Could not write .bzl config file %s", err) 319 } 320 err = ioutil.WriteFile(filepath.Join(dir, "BUILD"), []byte(bazel.GeneratedBazelFileWarning), 0644) 321 if err != nil { 322 return fmt.Errorf("Could not write BUILD config file %s", err) 323 } 324 325 return nil 326} 327 328// NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that 329// use the android package. 330func NullConfig(outDir, soongOutDir string) Config { 331 return Config{ 332 config: &config{ 333 outDir: outDir, 334 soongOutDir: soongOutDir, 335 fs: pathtools.OsFs, 336 }, 337 } 338} 339 340// TestConfig returns a Config object for testing. 341func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config { 342 envCopy := make(map[string]string) 343 for k, v := range env { 344 envCopy[k] = v 345 } 346 347 // Copy the real PATH value to the test environment, it's needed by 348 // NonHermeticHostSystemTool() used in x86_darwin_host.go 349 envCopy["PATH"] = os.Getenv("PATH") 350 351 config := &config{ 352 productVariables: productVariables{ 353 DeviceName: stringPtr("test_device"), 354 DeviceProduct: stringPtr("test_product"), 355 Platform_sdk_version: intPtr(30), 356 Platform_sdk_codename: stringPtr("S"), 357 Platform_base_sdk_extension_version: intPtr(1), 358 Platform_version_active_codenames: []string{"S", "Tiramisu"}, 359 DeviceSystemSdkVersions: []string{"14", "15"}, 360 Platform_systemsdk_versions: []string{"29", "30"}, 361 AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}, 362 AAPTPreferredConfig: stringPtr("xhdpi"), 363 AAPTCharacteristics: stringPtr("nosdcard"), 364 AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"}, 365 UncompressPrivAppDex: boolPtr(true), 366 ShippingApiLevel: stringPtr("30"), 367 }, 368 369 outDir: buildDir, 370 soongOutDir: filepath.Join(buildDir, "soong"), 371 captureBuild: true, 372 env: envCopy, 373 374 // Set testAllowNonExistentPaths so that test contexts don't need to specify every path 375 // passed to PathForSource or PathForModuleSrc. 376 TestAllowNonExistentPaths: true, 377 378 BazelContext: noopBazelContext{}, 379 } 380 config.deviceConfig = &deviceConfig{ 381 config: config, 382 } 383 config.TestProductVariables = &config.productVariables 384 385 config.mockFileSystem(bp, fs) 386 387 determineBuildOS(config) 388 389 return Config{config} 390} 391 392func modifyTestConfigToSupportArchMutator(testConfig Config) { 393 config := testConfig.config 394 395 config.Targets = map[OsType][]Target{ 396 Android: []Target{ 397 {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false}, 398 {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false}, 399 }, 400 config.BuildOS: []Target{ 401 {config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false}, 402 {config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false}, 403 }, 404 } 405 406 if runtime.GOOS == "darwin" { 407 config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1] 408 } 409 410 config.BuildOSTarget = config.Targets[config.BuildOS][0] 411 config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0] 412 config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0] 413 config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0] 414 config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64") 415 config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a") 416 config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm") 417 config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon") 418} 419 420func modifyTestConfigForMusl(config Config) { 421 delete(config.Targets, config.BuildOS) 422 config.productVariables.HostMusl = boolPtr(true) 423 determineBuildOS(config.config) 424 config.Targets[config.BuildOS] = []Target{ 425 {config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false}, 426 {config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false}, 427 } 428 429 config.BuildOSTarget = config.Targets[config.BuildOS][0] 430 config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0] 431} 432 433// TestArchConfig returns a Config object suitable for using for tests that 434// need to run the arch mutator. 435func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config { 436 testConfig := TestConfig(buildDir, env, bp, fs) 437 modifyTestConfigToSupportArchMutator(testConfig) 438 return testConfig 439} 440 441// ConfigForAdditionalRun is a config object which is "reset" for another 442// bootstrap run. Only per-run data is reset. Data which needs to persist across 443// multiple runs in the same program execution is carried over (such as Bazel 444// context or environment deps). 445func ConfigForAdditionalRun(c Config) (Config, error) { 446 newConfig, err := NewConfig(c.moduleListFile, c.runGoTests, c.outDir, c.soongOutDir, c.env) 447 if err != nil { 448 return Config{}, err 449 } 450 newConfig.BazelContext = c.BazelContext 451 newConfig.envDeps = c.envDeps 452 return newConfig, nil 453} 454 455// NewConfig creates a new Config object. The srcDir argument specifies the path 456// to the root source directory. It also loads the config file, if found. 457func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) { 458 // Make a config with default options. 459 config := &config{ 460 ProductVariablesFileName: filepath.Join(soongOutDir, productVariablesFileName), 461 462 env: availableEnv, 463 464 outDir: outDir, 465 soongOutDir: soongOutDir, 466 runGoTests: runGoTests, 467 multilibConflicts: make(map[ArchType]bool), 468 469 moduleListFile: moduleListFile, 470 fs: pathtools.NewOsFs(absSrcDir), 471 } 472 473 config.deviceConfig = &deviceConfig{ 474 config: config, 475 } 476 477 // Soundness check of the build and source directories. This won't catch strange 478 // configurations with symlinks, but at least checks the obvious case. 479 absBuildDir, err := filepath.Abs(soongOutDir) 480 if err != nil { 481 return Config{}, err 482 } 483 484 absSrcDir, err := filepath.Abs(".") 485 if err != nil { 486 return Config{}, err 487 } 488 489 if strings.HasPrefix(absSrcDir, absBuildDir) { 490 return Config{}, fmt.Errorf("Build dir must not contain source directory") 491 } 492 493 // Load any configurable options from the configuration file 494 err = loadConfig(config) 495 if err != nil { 496 return Config{}, err 497 } 498 499 KatiEnabledMarkerFile := filepath.Join(soongOutDir, ".soong.kati_enabled") 500 if _, err := os.Stat(absolutePath(KatiEnabledMarkerFile)); err == nil { 501 config.katiEnabled = true 502 } 503 504 determineBuildOS(config) 505 506 // Sets up the map of target OSes to the finer grained compilation targets 507 // that are configured from the product variables. 508 targets, err := decodeTargetProductVariables(config) 509 if err != nil { 510 return Config{}, err 511 } 512 513 // Make the CommonOS OsType available for all products. 514 targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]} 515 516 var archConfig []archConfig 517 if config.NdkAbis() { 518 archConfig = getNdkAbisConfig() 519 } else if config.AmlAbis() { 520 archConfig = getAmlAbisConfig() 521 } 522 523 if archConfig != nil { 524 androidTargets, err := decodeAndroidArchSettings(archConfig) 525 if err != nil { 526 return Config{}, err 527 } 528 targets[Android] = androidTargets 529 } 530 531 multilib := make(map[string]bool) 532 for _, target := range targets[Android] { 533 if seen := multilib[target.Arch.ArchType.Multilib]; seen { 534 config.multilibConflicts[target.Arch.ArchType] = true 535 } 536 multilib[target.Arch.ArchType.Multilib] = true 537 } 538 539 // Map of OS to compilation targets. 540 config.Targets = targets 541 542 // Compilation targets for host tools. 543 config.BuildOSTarget = config.Targets[config.BuildOS][0] 544 config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0] 545 546 // Compilation targets for Android. 547 if len(config.Targets[Android]) > 0 { 548 config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0] 549 config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0] 550 } 551 552 config.BazelContext, err = NewBazelContext(config) 553 config.bp2buildPackageConfig = bp2buildAllowlist 554 555 return Config{config}, err 556} 557 558// mockFileSystem replaces all reads with accesses to the provided map of 559// filenames to contents stored as a byte slice. 560func (c *config) mockFileSystem(bp string, fs map[string][]byte) { 561 mockFS := map[string][]byte{} 562 563 if _, exists := mockFS["Android.bp"]; !exists { 564 mockFS["Android.bp"] = []byte(bp) 565 } 566 567 for k, v := range fs { 568 mockFS[k] = v 569 } 570 571 // no module list file specified; find every file named Blueprints or Android.bp 572 pathsToParse := []string{} 573 for candidate := range mockFS { 574 base := filepath.Base(candidate) 575 if base == "Android.bp" { 576 pathsToParse = append(pathsToParse, candidate) 577 } 578 } 579 if len(pathsToParse) < 1 { 580 panic(fmt.Sprintf("No Blueprint or Android.bp files found in mock filesystem: %v\n", mockFS)) 581 } 582 mockFS[blueprint.MockModuleListFile] = []byte(strings.Join(pathsToParse, "\n")) 583 584 c.fs = pathtools.MockFs(mockFS) 585 c.mockBpList = blueprint.MockModuleListFile 586} 587 588func (c *config) SetAllowMissingDependencies() { 589 c.productVariables.Allow_missing_dependencies = proptools.BoolPtr(true) 590} 591 592// BlueprintToolLocation returns the directory containing build system tools 593// from Blueprint, like soong_zip and merge_zips. 594func (c *config) HostToolDir() string { 595 if c.KatiEnabled() { 596 return filepath.Join(c.outDir, "host", c.PrebuiltOS(), "bin") 597 } else { 598 return filepath.Join(c.soongOutDir, "host", c.PrebuiltOS(), "bin") 599 } 600} 601 602func (c *config) HostToolPath(ctx PathContext, tool string) Path { 603 path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", false, tool) 604 return path 605} 606 607func (c *config) HostJNIToolPath(ctx PathContext, lib string) Path { 608 ext := ".so" 609 if runtime.GOOS == "darwin" { 610 ext = ".dylib" 611 } 612 path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "lib64", false, lib+ext) 613 return path 614} 615 616func (c *config) HostJavaToolPath(ctx PathContext, tool string) Path { 617 path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "framework", false, tool) 618 return path 619} 620 621// PrebuiltOS returns the name of the host OS used in prebuilts directories. 622func (c *config) PrebuiltOS() string { 623 switch runtime.GOOS { 624 case "linux": 625 return "linux-x86" 626 case "darwin": 627 return "darwin-x86" 628 default: 629 panic("Unknown GOOS") 630 } 631} 632 633// GoRoot returns the path to the root directory of the Go toolchain. 634func (c *config) GoRoot() string { 635 return fmt.Sprintf("prebuilts/go/%s", c.PrebuiltOS()) 636} 637 638// PrebuiltBuildTool returns the path to a tool in the prebuilts directory containing 639// checked-in tools, like Kati, Ninja or Toybox, for the current host OS. 640func (c *config) PrebuiltBuildTool(ctx PathContext, tool string) Path { 641 return PathForSource(ctx, "prebuilts/build-tools", c.PrebuiltOS(), "bin", tool) 642} 643 644// CpPreserveSymlinksFlags returns the host-specific flag for the cp(1) command 645// to preserve symlinks. 646func (c *config) CpPreserveSymlinksFlags() string { 647 switch runtime.GOOS { 648 case "darwin": 649 return "-R" 650 case "linux": 651 return "-d" 652 default: 653 return "" 654 } 655} 656 657func (c *config) Getenv(key string) string { 658 var val string 659 var exists bool 660 c.envLock.Lock() 661 defer c.envLock.Unlock() 662 if c.envDeps == nil { 663 c.envDeps = make(map[string]string) 664 } 665 if val, exists = c.envDeps[key]; !exists { 666 if c.envFrozen { 667 panic("Cannot access new environment variables after envdeps are frozen") 668 } 669 val, _ = c.env[key] 670 c.envDeps[key] = val 671 } 672 return val 673} 674 675func (c *config) GetenvWithDefault(key string, defaultValue string) string { 676 ret := c.Getenv(key) 677 if ret == "" { 678 return defaultValue 679 } 680 return ret 681} 682 683func (c *config) IsEnvTrue(key string) bool { 684 value := c.Getenv(key) 685 return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true" 686} 687 688func (c *config) IsEnvFalse(key string) bool { 689 value := c.Getenv(key) 690 return value == "0" || value == "n" || value == "no" || value == "off" || value == "false" 691} 692 693// EnvDeps returns the environment variables this build depends on. The first 694// call to this function blocks future reads from the environment. 695func (c *config) EnvDeps() map[string]string { 696 c.envLock.Lock() 697 defer c.envLock.Unlock() 698 c.envFrozen = true 699 return c.envDeps 700} 701 702func (c *config) KatiEnabled() bool { 703 return c.katiEnabled 704} 705 706func (c *config) BuildId() string { 707 return String(c.productVariables.BuildId) 708} 709 710// BuildNumberFile returns the path to a text file containing metadata 711// representing the current build's number. 712// 713// Rules that want to reference the build number should read from this file 714// without depending on it. They will run whenever their other dependencies 715// require them to run and get the current build number. This ensures they don't 716// rebuild on every incremental build when the build number changes. 717func (c *config) BuildNumberFile(ctx PathContext) Path { 718 return PathForOutput(ctx, String(c.productVariables.BuildNumberFile)) 719} 720 721// DeviceName returns the name of the current device target. 722// TODO: take an AndroidModuleContext to select the device name for multi-device builds 723func (c *config) DeviceName() string { 724 return *c.productVariables.DeviceName 725} 726 727// DeviceProduct returns the current product target. There could be multiple of 728// these per device type. 729// 730// NOTE: Do not base conditional logic on this value. It may break product 731// inheritance. 732func (c *config) DeviceProduct() string { 733 return *c.productVariables.DeviceProduct 734} 735 736func (c *config) DeviceResourceOverlays() []string { 737 return c.productVariables.DeviceResourceOverlays 738} 739 740func (c *config) ProductResourceOverlays() []string { 741 return c.productVariables.ProductResourceOverlays 742} 743 744func (c *config) PlatformVersionName() string { 745 return String(c.productVariables.Platform_version_name) 746} 747 748func (c *config) PlatformSdkVersion() ApiLevel { 749 return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version) 750} 751 752func (c *config) PlatformSdkCodename() string { 753 return String(c.productVariables.Platform_sdk_codename) 754} 755 756func (c *config) PlatformSdkExtensionVersion() int { 757 return *c.productVariables.Platform_sdk_extension_version 758} 759 760func (c *config) PlatformBaseSdkExtensionVersion() int { 761 return *c.productVariables.Platform_base_sdk_extension_version 762} 763 764func (c *config) PlatformSecurityPatch() string { 765 return String(c.productVariables.Platform_security_patch) 766} 767 768func (c *config) PlatformPreviewSdkVersion() string { 769 return String(c.productVariables.Platform_preview_sdk_version) 770} 771 772func (c *config) PlatformMinSupportedTargetSdkVersion() string { 773 return String(c.productVariables.Platform_min_supported_target_sdk_version) 774} 775 776func (c *config) PlatformBaseOS() string { 777 return String(c.productVariables.Platform_base_os) 778} 779 780func (c *config) PlatformVersionLastStable() string { 781 return String(c.productVariables.Platform_version_last_stable) 782} 783 784func (c *config) MinSupportedSdkVersion() ApiLevel { 785 return uncheckedFinalApiLevel(19) 786} 787 788func (c *config) FinalApiLevels() []ApiLevel { 789 var levels []ApiLevel 790 for i := 1; i <= c.PlatformSdkVersion().FinalOrFutureInt(); i++ { 791 levels = append(levels, uncheckedFinalApiLevel(i)) 792 } 793 return levels 794} 795 796func (c *config) PreviewApiLevels() []ApiLevel { 797 var levels []ApiLevel 798 for i, codename := range c.PlatformVersionActiveCodenames() { 799 levels = append(levels, ApiLevel{ 800 value: codename, 801 number: i, 802 isPreview: true, 803 }) 804 } 805 return levels 806} 807 808func (c *config) LatestPreviewApiLevel() ApiLevel { 809 level := NoneApiLevel 810 for _, l := range c.PreviewApiLevels() { 811 if l.GreaterThan(level) { 812 level = l 813 } 814 } 815 return level 816} 817 818func (c *config) AllSupportedApiLevels() []ApiLevel { 819 var levels []ApiLevel 820 levels = append(levels, c.FinalApiLevels()...) 821 return append(levels, c.PreviewApiLevels()...) 822} 823 824// DefaultAppTargetSdk returns the API level that platform apps are targeting. 825// This converts a codename to the exact ApiLevel it represents. 826func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel { 827 if Bool(c.productVariables.Platform_sdk_final) { 828 return c.PlatformSdkVersion() 829 } 830 codename := c.PlatformSdkCodename() 831 if codename == "" { 832 return NoneApiLevel 833 } 834 if codename == "REL" { 835 panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true") 836 } 837 return ApiLevelOrPanic(ctx, codename) 838} 839 840func (c *config) AppsDefaultVersionName() string { 841 return String(c.productVariables.AppsDefaultVersionName) 842} 843 844// Codenames that are active in the current lunch target. 845func (c *config) PlatformVersionActiveCodenames() []string { 846 return c.productVariables.Platform_version_active_codenames 847} 848 849func (c *config) ProductAAPTConfig() []string { 850 return c.productVariables.AAPTConfig 851} 852 853func (c *config) ProductAAPTPreferredConfig() string { 854 return String(c.productVariables.AAPTPreferredConfig) 855} 856 857func (c *config) ProductAAPTCharacteristics() string { 858 return String(c.productVariables.AAPTCharacteristics) 859} 860 861func (c *config) ProductAAPTPrebuiltDPI() []string { 862 return c.productVariables.AAPTPrebuiltDPI 863} 864 865func (c *config) DefaultAppCertificateDir(ctx PathContext) SourcePath { 866 defaultCert := String(c.productVariables.DefaultAppCertificate) 867 if defaultCert != "" { 868 return PathForSource(ctx, filepath.Dir(defaultCert)) 869 } 870 return PathForSource(ctx, "build/make/target/product/security") 871} 872 873func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) { 874 defaultCert := String(c.productVariables.DefaultAppCertificate) 875 if defaultCert != "" { 876 return PathForSource(ctx, defaultCert+".x509.pem"), PathForSource(ctx, defaultCert+".pk8") 877 } 878 defaultDir := c.DefaultAppCertificateDir(ctx) 879 return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8") 880} 881 882func (c *config) ApexKeyDir(ctx ModuleContext) SourcePath { 883 // TODO(b/121224311): define another variable such as TARGET_APEX_KEY_OVERRIDE 884 defaultCert := String(c.productVariables.DefaultAppCertificate) 885 if defaultCert == "" || filepath.Dir(defaultCert) == "build/make/target/product/security" { 886 // When defaultCert is unset or is set to the testkeys path, use the APEX keys 887 // that is under the module dir 888 return pathForModuleSrc(ctx) 889 } 890 // If not, APEX keys are under the specified directory 891 return PathForSource(ctx, filepath.Dir(defaultCert)) 892} 893 894// AllowMissingDependencies configures Blueprint/Soong to not fail when modules 895// are configured to depend on non-existent modules. Note that this does not 896// affect missing input dependencies at the Ninja level. 897func (c *config) AllowMissingDependencies() bool { 898 return Bool(c.productVariables.Allow_missing_dependencies) 899} 900 901// Returns true if a full platform source tree cannot be assumed. 902func (c *config) UnbundledBuild() bool { 903 return Bool(c.productVariables.Unbundled_build) 904} 905 906// Returns true if building apps that aren't bundled with the platform. 907// UnbundledBuild() is always true when this is true. 908func (c *config) UnbundledBuildApps() bool { 909 return len(c.productVariables.Unbundled_build_apps) > 0 910} 911 912// Returns true if building image that aren't bundled with the platform. 913// UnbundledBuild() is always true when this is true. 914func (c *config) UnbundledBuildImage() bool { 915 return Bool(c.productVariables.Unbundled_build_image) 916} 917 918// Returns true if building modules against prebuilt SDKs. 919func (c *config) AlwaysUsePrebuiltSdks() bool { 920 return Bool(c.productVariables.Always_use_prebuilt_sdks) 921} 922 923func (c *config) MinimizeJavaDebugInfo() bool { 924 return Bool(c.productVariables.MinimizeJavaDebugInfo) && !Bool(c.productVariables.Eng) 925} 926 927func (c *config) Debuggable() bool { 928 return Bool(c.productVariables.Debuggable) 929} 930 931func (c *config) Eng() bool { 932 return Bool(c.productVariables.Eng) 933} 934 935// DevicePrimaryArchType returns the ArchType for the first configured device architecture, or 936// Common if there are no device architectures. 937func (c *config) DevicePrimaryArchType() ArchType { 938 if androidTargets := c.Targets[Android]; len(androidTargets) > 0 { 939 return androidTargets[0].Arch.ArchType 940 } 941 return Common 942} 943 944func (c *config) SanitizeHost() []string { 945 return append([]string(nil), c.productVariables.SanitizeHost...) 946} 947 948func (c *config) SanitizeDevice() []string { 949 return append([]string(nil), c.productVariables.SanitizeDevice...) 950} 951 952func (c *config) SanitizeDeviceDiag() []string { 953 return append([]string(nil), c.productVariables.SanitizeDeviceDiag...) 954} 955 956func (c *config) SanitizeDeviceArch() []string { 957 return append([]string(nil), c.productVariables.SanitizeDeviceArch...) 958} 959 960func (c *config) EnableCFI() bool { 961 if c.productVariables.EnableCFI == nil { 962 return true 963 } 964 return *c.productVariables.EnableCFI 965} 966 967func (c *config) DisableScudo() bool { 968 return Bool(c.productVariables.DisableScudo) 969} 970 971func (c *config) Android64() bool { 972 for _, t := range c.Targets[Android] { 973 if t.Arch.ArchType.Multilib == "lib64" { 974 return true 975 } 976 } 977 978 return false 979} 980 981func (c *config) UseGoma() bool { 982 return Bool(c.productVariables.UseGoma) 983} 984 985func (c *config) UseRBE() bool { 986 return Bool(c.productVariables.UseRBE) 987} 988 989func (c *config) UseRBEJAVAC() bool { 990 return Bool(c.productVariables.UseRBEJAVAC) 991} 992 993func (c *config) UseRBER8() bool { 994 return Bool(c.productVariables.UseRBER8) 995} 996 997func (c *config) UseRBED8() bool { 998 return Bool(c.productVariables.UseRBED8) 999} 1000 1001func (c *config) UseRemoteBuild() bool { 1002 return c.UseGoma() || c.UseRBE() 1003} 1004 1005func (c *config) RunErrorProne() bool { 1006 return c.IsEnvTrue("RUN_ERROR_PRONE") 1007} 1008 1009// XrefCorpusName returns the Kythe cross-reference corpus name. 1010func (c *config) XrefCorpusName() string { 1011 return c.Getenv("XREF_CORPUS") 1012} 1013 1014// XrefCuEncoding returns the compilation unit encoding to use for Kythe code 1015// xrefs. Can be 'json' (default), 'proto' or 'all'. 1016func (c *config) XrefCuEncoding() string { 1017 if enc := c.Getenv("KYTHE_KZIP_ENCODING"); enc != "" { 1018 return enc 1019 } 1020 return "json" 1021} 1022 1023// XrefCuJavaSourceMax returns the maximum number of the Java source files 1024// in a single compilation unit 1025const xrefJavaSourceFileMaxDefault = "1000" 1026 1027func (c Config) XrefCuJavaSourceMax() string { 1028 v := c.Getenv("KYTHE_JAVA_SOURCE_BATCH_SIZE") 1029 if v == "" { 1030 return xrefJavaSourceFileMaxDefault 1031 } 1032 if _, err := strconv.ParseUint(v, 0, 0); err != nil { 1033 fmt.Fprintf(os.Stderr, 1034 "bad KYTHE_JAVA_SOURCE_BATCH_SIZE value: %s, will use %s", 1035 err, xrefJavaSourceFileMaxDefault) 1036 return xrefJavaSourceFileMaxDefault 1037 } 1038 return v 1039 1040} 1041 1042func (c *config) EmitXrefRules() bool { 1043 return c.XrefCorpusName() != "" 1044} 1045 1046func (c *config) ClangTidy() bool { 1047 return Bool(c.productVariables.ClangTidy) 1048} 1049 1050func (c *config) TidyChecks() string { 1051 if c.productVariables.TidyChecks == nil { 1052 return "" 1053 } 1054 return *c.productVariables.TidyChecks 1055} 1056 1057func (c *config) LibartImgHostBaseAddress() string { 1058 return "0x60000000" 1059} 1060 1061func (c *config) LibartImgDeviceBaseAddress() string { 1062 return "0x70000000" 1063} 1064 1065func (c *config) ArtUseReadBarrier() bool { 1066 return Bool(c.productVariables.ArtUseReadBarrier) 1067} 1068 1069// Enforce Runtime Resource Overlays for a module. RROs supersede static RROs, 1070// but some modules still depend on it. 1071// 1072// More info: https://source.android.com/devices/architecture/rros 1073func (c *config) EnforceRROForModule(name string) bool { 1074 enforceList := c.productVariables.EnforceRROTargets 1075 1076 if len(enforceList) > 0 { 1077 if InList("*", enforceList) { 1078 return true 1079 } 1080 return InList(name, enforceList) 1081 } 1082 return false 1083} 1084func (c *config) EnforceRROExcludedOverlay(path string) bool { 1085 excluded := c.productVariables.EnforceRROExcludedOverlays 1086 if len(excluded) > 0 { 1087 return HasAnyPrefix(path, excluded) 1088 } 1089 return false 1090} 1091 1092func (c *config) ExportedNamespaces() []string { 1093 return append([]string(nil), c.productVariables.NamespacesToExport...) 1094} 1095 1096func (c *config) IncludeTags() []string { 1097 return c.productVariables.IncludeTags 1098} 1099 1100func (c *config) HostStaticBinaries() bool { 1101 return Bool(c.productVariables.HostStaticBinaries) 1102} 1103 1104func (c *config) UncompressPrivAppDex() bool { 1105 return Bool(c.productVariables.UncompressPrivAppDex) 1106} 1107 1108func (c *config) ModulesLoadedByPrivilegedModules() []string { 1109 return c.productVariables.ModulesLoadedByPrivilegedModules 1110} 1111 1112// DexpreoptGlobalConfigPath returns the path to the dexpreopt.config file in 1113// the output directory, if it was created during the product configuration 1114// phase by Kati. 1115func (c *config) DexpreoptGlobalConfigPath(ctx PathContext) OptionalPath { 1116 if c.productVariables.DexpreoptGlobalConfig == nil { 1117 return OptionalPathForPath(nil) 1118 } 1119 return OptionalPathForPath( 1120 pathForBuildToolDep(ctx, *c.productVariables.DexpreoptGlobalConfig)) 1121} 1122 1123// DexpreoptGlobalConfig returns the raw byte contents of the dexpreopt global 1124// configuration. Since the configuration file was created by Kati during 1125// product configuration (externally of soong_build), it's not tracked, so we 1126// also manually add a Ninja file dependency on the configuration file to the 1127// rule that creates the main build.ninja file. This ensures that build.ninja is 1128// regenerated correctly if dexpreopt.config changes. 1129func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) { 1130 path := c.DexpreoptGlobalConfigPath(ctx) 1131 if !path.Valid() { 1132 return nil, nil 1133 } 1134 ctx.AddNinjaFileDeps(path.String()) 1135 return ioutil.ReadFile(absolutePath(path.String())) 1136} 1137 1138func (c *deviceConfig) WithDexpreopt() bool { 1139 return c.config.productVariables.WithDexpreopt 1140} 1141 1142func (c *config) FrameworksBaseDirExists(ctx PathContext) bool { 1143 return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid() 1144} 1145 1146func (c *config) VndkSnapshotBuildArtifacts() bool { 1147 return Bool(c.productVariables.VndkSnapshotBuildArtifacts) 1148} 1149 1150func (c *config) HasMultilibConflict(arch ArchType) bool { 1151 return c.multilibConflicts[arch] 1152} 1153 1154func (c *config) PrebuiltHiddenApiDir(ctx PathContext) string { 1155 return String(c.productVariables.PrebuiltHiddenApiDir) 1156} 1157 1158func (c *deviceConfig) Arches() []Arch { 1159 var arches []Arch 1160 for _, target := range c.config.Targets[Android] { 1161 arches = append(arches, target.Arch) 1162 } 1163 return arches 1164} 1165 1166func (c *deviceConfig) BinderBitness() string { 1167 is32BitBinder := c.config.productVariables.Binder32bit 1168 if is32BitBinder != nil && *is32BitBinder { 1169 return "32" 1170 } 1171 return "64" 1172} 1173 1174func (c *deviceConfig) VendorPath() string { 1175 if c.config.productVariables.VendorPath != nil { 1176 return *c.config.productVariables.VendorPath 1177 } 1178 return "vendor" 1179} 1180 1181func (c *deviceConfig) VndkVersion() string { 1182 return String(c.config.productVariables.DeviceVndkVersion) 1183} 1184 1185func (c *deviceConfig) RecoverySnapshotVersion() string { 1186 return String(c.config.productVariables.RecoverySnapshotVersion) 1187} 1188 1189func (c *deviceConfig) CurrentApiLevelForVendorModules() string { 1190 return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current") 1191} 1192 1193func (c *deviceConfig) PlatformVndkVersion() string { 1194 return String(c.config.productVariables.Platform_vndk_version) 1195} 1196 1197func (c *deviceConfig) ProductVndkVersion() string { 1198 return String(c.config.productVariables.ProductVndkVersion) 1199} 1200 1201func (c *deviceConfig) ExtraVndkVersions() []string { 1202 return c.config.productVariables.ExtraVndkVersions 1203} 1204 1205func (c *deviceConfig) VndkUseCoreVariant() bool { 1206 return Bool(c.config.productVariables.VndkUseCoreVariant) 1207} 1208 1209func (c *deviceConfig) SystemSdkVersions() []string { 1210 return c.config.productVariables.DeviceSystemSdkVersions 1211} 1212 1213func (c *deviceConfig) PlatformSystemSdkVersions() []string { 1214 return c.config.productVariables.Platform_systemsdk_versions 1215} 1216 1217func (c *deviceConfig) OdmPath() string { 1218 if c.config.productVariables.OdmPath != nil { 1219 return *c.config.productVariables.OdmPath 1220 } 1221 return "odm" 1222} 1223 1224func (c *deviceConfig) ProductPath() string { 1225 if c.config.productVariables.ProductPath != nil { 1226 return *c.config.productVariables.ProductPath 1227 } 1228 return "product" 1229} 1230 1231func (c *deviceConfig) SystemExtPath() string { 1232 if c.config.productVariables.SystemExtPath != nil { 1233 return *c.config.productVariables.SystemExtPath 1234 } 1235 return "system_ext" 1236} 1237 1238func (c *deviceConfig) BtConfigIncludeDir() string { 1239 return String(c.config.productVariables.BtConfigIncludeDir) 1240} 1241 1242func (c *deviceConfig) DeviceKernelHeaderDirs() []string { 1243 return c.config.productVariables.DeviceKernelHeaders 1244} 1245 1246// JavaCoverageEnabledForPath returns whether Java code coverage is enabled for 1247// path. Coverage is enabled by default when the product variable 1248// JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is 1249// enabled for any path which is part of this variable (and not part of the 1250// JavaCoverageExcludePaths product variable). Value "*" in JavaCoveragePaths 1251// represents any path. 1252func (c *deviceConfig) JavaCoverageEnabledForPath(path string) bool { 1253 coverage := false 1254 if len(c.config.productVariables.JavaCoveragePaths) == 0 || 1255 InList("*", c.config.productVariables.JavaCoveragePaths) || 1256 HasAnyPrefix(path, c.config.productVariables.JavaCoveragePaths) { 1257 coverage = true 1258 } 1259 if coverage && len(c.config.productVariables.JavaCoverageExcludePaths) > 0 { 1260 if HasAnyPrefix(path, c.config.productVariables.JavaCoverageExcludePaths) { 1261 coverage = false 1262 } 1263 } 1264 return coverage 1265} 1266 1267// Returns true if gcov or clang coverage is enabled. 1268func (c *deviceConfig) NativeCoverageEnabled() bool { 1269 return Bool(c.config.productVariables.GcovCoverage) || 1270 Bool(c.config.productVariables.ClangCoverage) 1271} 1272 1273func (c *deviceConfig) ClangCoverageEnabled() bool { 1274 return Bool(c.config.productVariables.ClangCoverage) 1275} 1276 1277func (c *deviceConfig) ClangCoverageContinuousMode() bool { 1278 return Bool(c.config.productVariables.ClangCoverageContinuousMode) 1279} 1280 1281func (c *deviceConfig) GcovCoverageEnabled() bool { 1282 return Bool(c.config.productVariables.GcovCoverage) 1283} 1284 1285// NativeCoverageEnabledForPath returns whether (GCOV- or Clang-based) native 1286// code coverage is enabled for path. By default, coverage is not enabled for a 1287// given path unless it is part of the NativeCoveragePaths product variable (and 1288// not part of the NativeCoverageExcludePaths product variable). Value "*" in 1289// NativeCoveragePaths represents any path. 1290func (c *deviceConfig) NativeCoverageEnabledForPath(path string) bool { 1291 coverage := false 1292 if len(c.config.productVariables.NativeCoveragePaths) > 0 { 1293 if InList("*", c.config.productVariables.NativeCoveragePaths) || HasAnyPrefix(path, c.config.productVariables.NativeCoveragePaths) { 1294 coverage = true 1295 } 1296 } 1297 if coverage && len(c.config.productVariables.NativeCoverageExcludePaths) > 0 { 1298 if HasAnyPrefix(path, c.config.productVariables.NativeCoverageExcludePaths) { 1299 coverage = false 1300 } 1301 } 1302 return coverage 1303} 1304 1305func (c *deviceConfig) AfdoAdditionalProfileDirs() []string { 1306 return c.config.productVariables.AfdoAdditionalProfileDirs 1307} 1308 1309func (c *deviceConfig) PgoAdditionalProfileDirs() []string { 1310 return c.config.productVariables.PgoAdditionalProfileDirs 1311} 1312 1313func (c *deviceConfig) VendorSepolicyDirs() []string { 1314 return c.config.productVariables.BoardVendorSepolicyDirs 1315} 1316 1317func (c *deviceConfig) OdmSepolicyDirs() []string { 1318 return c.config.productVariables.BoardOdmSepolicyDirs 1319} 1320 1321func (c *deviceConfig) SystemExtPublicSepolicyDirs() []string { 1322 return c.config.productVariables.SystemExtPublicSepolicyDirs 1323} 1324 1325func (c *deviceConfig) SystemExtPrivateSepolicyDirs() []string { 1326 return c.config.productVariables.SystemExtPrivateSepolicyDirs 1327} 1328 1329func (c *deviceConfig) SepolicyM4Defs() []string { 1330 return c.config.productVariables.BoardSepolicyM4Defs 1331} 1332 1333func (c *deviceConfig) OverrideManifestPackageNameFor(name string) (manifestName string, overridden bool) { 1334 return findOverrideValue(c.config.productVariables.ManifestPackageNameOverrides, name, 1335 "invalid override rule %q in PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES should be <module_name>:<manifest_name>") 1336} 1337 1338func (c *deviceConfig) OverrideCertificateFor(name string) (certificatePath string, overridden bool) { 1339 return findOverrideValue(c.config.productVariables.CertificateOverrides, name, 1340 "invalid override rule %q in PRODUCT_CERTIFICATE_OVERRIDES should be <module_name>:<certificate_module_name>") 1341} 1342 1343func (c *deviceConfig) OverridePackageNameFor(name string) string { 1344 newName, overridden := findOverrideValue( 1345 c.config.productVariables.PackageNameOverrides, 1346 name, 1347 "invalid override rule %q in PRODUCT_PACKAGE_NAME_OVERRIDES should be <module_name>:<package_name>") 1348 if overridden { 1349 return newName 1350 } 1351 return name 1352} 1353 1354func findOverrideValue(overrides []string, name string, errorMsg string) (newValue string, overridden bool) { 1355 if overrides == nil || len(overrides) == 0 { 1356 return "", false 1357 } 1358 for _, o := range overrides { 1359 split := strings.Split(o, ":") 1360 if len(split) != 2 { 1361 // This shouldn't happen as this is first checked in make, but just in case. 1362 panic(fmt.Errorf(errorMsg, o)) 1363 } 1364 if matchPattern(split[0], name) { 1365 return substPattern(split[0], split[1], name), true 1366 } 1367 } 1368 return "", false 1369} 1370 1371func (c *deviceConfig) ApexGlobalMinSdkVersionOverride() string { 1372 return String(c.config.productVariables.ApexGlobalMinSdkVersionOverride) 1373} 1374 1375func (c *config) IntegerOverflowDisabledForPath(path string) bool { 1376 if len(c.productVariables.IntegerOverflowExcludePaths) == 0 { 1377 return false 1378 } 1379 return HasAnyPrefix(path, c.productVariables.IntegerOverflowExcludePaths) 1380} 1381 1382func (c *config) CFIDisabledForPath(path string) bool { 1383 if len(c.productVariables.CFIExcludePaths) == 0 { 1384 return false 1385 } 1386 return HasAnyPrefix(path, c.productVariables.CFIExcludePaths) 1387} 1388 1389func (c *config) CFIEnabledForPath(path string) bool { 1390 if len(c.productVariables.CFIIncludePaths) == 0 { 1391 return false 1392 } 1393 return HasAnyPrefix(path, c.productVariables.CFIIncludePaths) && !c.CFIDisabledForPath(path) 1394} 1395 1396func (c *config) MemtagHeapDisabledForPath(path string) bool { 1397 if len(c.productVariables.MemtagHeapExcludePaths) == 0 { 1398 return false 1399 } 1400 return HasAnyPrefix(path, c.productVariables.MemtagHeapExcludePaths) 1401} 1402 1403func (c *config) MemtagHeapAsyncEnabledForPath(path string) bool { 1404 if len(c.productVariables.MemtagHeapAsyncIncludePaths) == 0 { 1405 return false 1406 } 1407 return HasAnyPrefix(path, c.productVariables.MemtagHeapAsyncIncludePaths) && !c.MemtagHeapDisabledForPath(path) 1408} 1409 1410func (c *config) MemtagHeapSyncEnabledForPath(path string) bool { 1411 if len(c.productVariables.MemtagHeapSyncIncludePaths) == 0 { 1412 return false 1413 } 1414 return HasAnyPrefix(path, c.productVariables.MemtagHeapSyncIncludePaths) && !c.MemtagHeapDisabledForPath(path) 1415} 1416 1417func (c *config) VendorConfig(name string) VendorConfig { 1418 return soongconfig.Config(c.productVariables.VendorVars[name]) 1419} 1420 1421func (c *config) NdkAbis() bool { 1422 return Bool(c.productVariables.Ndk_abis) 1423} 1424 1425func (c *config) AmlAbis() bool { 1426 return Bool(c.productVariables.Aml_abis) 1427} 1428 1429func (c *config) FlattenApex() bool { 1430 return Bool(c.productVariables.Flatten_apex) 1431} 1432 1433func (c *config) ForceApexSymlinkOptimization() bool { 1434 return Bool(c.productVariables.ForceApexSymlinkOptimization) 1435} 1436 1437func (c *config) CompressedApex() bool { 1438 return Bool(c.productVariables.CompressedApex) 1439} 1440 1441func (c *config) EnforceSystemCertificate() bool { 1442 return Bool(c.productVariables.EnforceSystemCertificate) 1443} 1444 1445func (c *config) EnforceSystemCertificateAllowList() []string { 1446 return c.productVariables.EnforceSystemCertificateAllowList 1447} 1448 1449func (c *config) EnforceProductPartitionInterface() bool { 1450 return Bool(c.productVariables.EnforceProductPartitionInterface) 1451} 1452 1453func (c *config) EnforceInterPartitionJavaSdkLibrary() bool { 1454 return Bool(c.productVariables.EnforceInterPartitionJavaSdkLibrary) 1455} 1456 1457func (c *config) InterPartitionJavaLibraryAllowList() []string { 1458 return c.productVariables.InterPartitionJavaLibraryAllowList 1459} 1460 1461func (c *config) InstallExtraFlattenedApexes() bool { 1462 return Bool(c.productVariables.InstallExtraFlattenedApexes) 1463} 1464 1465func (c *config) ProductHiddenAPIStubs() []string { 1466 return c.productVariables.ProductHiddenAPIStubs 1467} 1468 1469func (c *config) ProductHiddenAPIStubsSystem() []string { 1470 return c.productVariables.ProductHiddenAPIStubsSystem 1471} 1472 1473func (c *config) ProductHiddenAPIStubsTest() []string { 1474 return c.productVariables.ProductHiddenAPIStubsTest 1475} 1476 1477func (c *deviceConfig) TargetFSConfigGen() []string { 1478 return c.config.productVariables.TargetFSConfigGen 1479} 1480 1481func (c *config) ProductPublicSepolicyDirs() []string { 1482 return c.productVariables.ProductPublicSepolicyDirs 1483} 1484 1485func (c *config) ProductPrivateSepolicyDirs() []string { 1486 return c.productVariables.ProductPrivateSepolicyDirs 1487} 1488 1489func (c *config) MissingUsesLibraries() []string { 1490 return c.productVariables.MissingUsesLibraries 1491} 1492 1493func (c *deviceConfig) DeviceArch() string { 1494 return String(c.config.productVariables.DeviceArch) 1495} 1496 1497func (c *deviceConfig) DeviceArchVariant() string { 1498 return String(c.config.productVariables.DeviceArchVariant) 1499} 1500 1501func (c *deviceConfig) DeviceSecondaryArch() string { 1502 return String(c.config.productVariables.DeviceSecondaryArch) 1503} 1504 1505func (c *deviceConfig) DeviceSecondaryArchVariant() string { 1506 return String(c.config.productVariables.DeviceSecondaryArchVariant) 1507} 1508 1509func (c *deviceConfig) BoardUsesRecoveryAsBoot() bool { 1510 return Bool(c.config.productVariables.BoardUsesRecoveryAsBoot) 1511} 1512 1513func (c *deviceConfig) BoardKernelBinaries() []string { 1514 return c.config.productVariables.BoardKernelBinaries 1515} 1516 1517func (c *deviceConfig) BoardKernelModuleInterfaceVersions() []string { 1518 return c.config.productVariables.BoardKernelModuleInterfaceVersions 1519} 1520 1521func (c *deviceConfig) BoardMoveRecoveryResourcesToVendorBoot() bool { 1522 return Bool(c.config.productVariables.BoardMoveRecoveryResourcesToVendorBoot) 1523} 1524 1525func (c *deviceConfig) PlatformSepolicyVersion() string { 1526 return String(c.config.productVariables.PlatformSepolicyVersion) 1527} 1528 1529func (c *deviceConfig) TotSepolicyVersion() string { 1530 return String(c.config.productVariables.TotSepolicyVersion) 1531} 1532 1533func (c *deviceConfig) PlatformSepolicyCompatVersions() []string { 1534 return c.config.productVariables.PlatformSepolicyCompatVersions 1535} 1536 1537func (c *deviceConfig) BoardSepolicyVers() string { 1538 if ver := String(c.config.productVariables.BoardSepolicyVers); ver != "" { 1539 return ver 1540 } 1541 return c.PlatformSepolicyVersion() 1542} 1543 1544func (c *deviceConfig) BoardPlatVendorPolicy() []string { 1545 return c.config.productVariables.BoardPlatVendorPolicy 1546} 1547 1548func (c *deviceConfig) BoardReqdMaskPolicy() []string { 1549 return c.config.productVariables.BoardReqdMaskPolicy 1550} 1551 1552func (c *deviceConfig) BoardSystemExtPublicPrebuiltDirs() []string { 1553 return c.config.productVariables.BoardSystemExtPublicPrebuiltDirs 1554} 1555 1556func (c *deviceConfig) BoardSystemExtPrivatePrebuiltDirs() []string { 1557 return c.config.productVariables.BoardSystemExtPrivatePrebuiltDirs 1558} 1559 1560func (c *deviceConfig) BoardProductPublicPrebuiltDirs() []string { 1561 return c.config.productVariables.BoardProductPublicPrebuiltDirs 1562} 1563 1564func (c *deviceConfig) BoardProductPrivatePrebuiltDirs() []string { 1565 return c.config.productVariables.BoardProductPrivatePrebuiltDirs 1566} 1567 1568func (c *deviceConfig) SystemExtSepolicyPrebuiltApiDir() string { 1569 return String(c.config.productVariables.SystemExtSepolicyPrebuiltApiDir) 1570} 1571 1572func (c *deviceConfig) ProductSepolicyPrebuiltApiDir() string { 1573 return String(c.config.productVariables.ProductSepolicyPrebuiltApiDir) 1574} 1575 1576func (c *deviceConfig) IsPartnerTrebleSepolicyTestEnabled() bool { 1577 return c.SystemExtSepolicyPrebuiltApiDir() != "" || c.ProductSepolicyPrebuiltApiDir() != "" 1578} 1579 1580func (c *deviceConfig) DirectedVendorSnapshot() bool { 1581 return c.config.productVariables.DirectedVendorSnapshot 1582} 1583 1584func (c *deviceConfig) VendorSnapshotModules() map[string]bool { 1585 return c.config.productVariables.VendorSnapshotModules 1586} 1587 1588func (c *deviceConfig) DirectedRecoverySnapshot() bool { 1589 return c.config.productVariables.DirectedRecoverySnapshot 1590} 1591 1592func (c *deviceConfig) RecoverySnapshotModules() map[string]bool { 1593 return c.config.productVariables.RecoverySnapshotModules 1594} 1595 1596func createDirsMap(previous map[string]bool, dirs []string) (map[string]bool, error) { 1597 var ret = make(map[string]bool) 1598 for _, dir := range dirs { 1599 clean := filepath.Clean(dir) 1600 if previous[clean] || ret[clean] { 1601 return nil, fmt.Errorf("Duplicate entry %s", dir) 1602 } 1603 ret[clean] = true 1604 } 1605 return ret, nil 1606} 1607 1608func (c *deviceConfig) createDirsMapOnce(onceKey OnceKey, previous map[string]bool, dirs []string) map[string]bool { 1609 dirMap := c.Once(onceKey, func() interface{} { 1610 ret, err := createDirsMap(previous, dirs) 1611 if err != nil { 1612 panic(fmt.Errorf("%s: %w", onceKey.key, err)) 1613 } 1614 return ret 1615 }) 1616 if dirMap == nil { 1617 return nil 1618 } 1619 return dirMap.(map[string]bool) 1620} 1621 1622var vendorSnapshotDirsExcludedKey = NewOnceKey("VendorSnapshotDirsExcludedMap") 1623 1624func (c *deviceConfig) VendorSnapshotDirsExcludedMap() map[string]bool { 1625 return c.createDirsMapOnce(vendorSnapshotDirsExcludedKey, nil, 1626 c.config.productVariables.VendorSnapshotDirsExcluded) 1627} 1628 1629var vendorSnapshotDirsIncludedKey = NewOnceKey("VendorSnapshotDirsIncludedMap") 1630 1631func (c *deviceConfig) VendorSnapshotDirsIncludedMap() map[string]bool { 1632 excludedMap := c.VendorSnapshotDirsExcludedMap() 1633 return c.createDirsMapOnce(vendorSnapshotDirsIncludedKey, excludedMap, 1634 c.config.productVariables.VendorSnapshotDirsIncluded) 1635} 1636 1637var recoverySnapshotDirsExcludedKey = NewOnceKey("RecoverySnapshotDirsExcludedMap") 1638 1639func (c *deviceConfig) RecoverySnapshotDirsExcludedMap() map[string]bool { 1640 return c.createDirsMapOnce(recoverySnapshotDirsExcludedKey, nil, 1641 c.config.productVariables.RecoverySnapshotDirsExcluded) 1642} 1643 1644var recoverySnapshotDirsIncludedKey = NewOnceKey("RecoverySnapshotDirsIncludedMap") 1645 1646func (c *deviceConfig) RecoverySnapshotDirsIncludedMap() map[string]bool { 1647 excludedMap := c.RecoverySnapshotDirsExcludedMap() 1648 return c.createDirsMapOnce(recoverySnapshotDirsIncludedKey, excludedMap, 1649 c.config.productVariables.RecoverySnapshotDirsIncluded) 1650} 1651 1652func (c *deviceConfig) HostFakeSnapshotEnabled() bool { 1653 return c.config.productVariables.HostFakeSnapshotEnabled 1654} 1655 1656func (c *deviceConfig) ShippingApiLevel() ApiLevel { 1657 if c.config.productVariables.ShippingApiLevel == nil { 1658 return NoneApiLevel 1659 } 1660 apiLevel, _ := strconv.Atoi(*c.config.productVariables.ShippingApiLevel) 1661 return uncheckedFinalApiLevel(apiLevel) 1662} 1663 1664func (c *deviceConfig) BuildBrokenEnforceSyspropOwner() bool { 1665 return c.config.productVariables.BuildBrokenEnforceSyspropOwner 1666} 1667 1668func (c *deviceConfig) BuildBrokenTrebleSyspropNeverallow() bool { 1669 return c.config.productVariables.BuildBrokenTrebleSyspropNeverallow 1670} 1671 1672func (c *deviceConfig) BuildDebugfsRestrictionsEnabled() bool { 1673 return c.config.productVariables.BuildDebugfsRestrictionsEnabled 1674} 1675 1676func (c *deviceConfig) BuildBrokenVendorPropertyNamespace() bool { 1677 return c.config.productVariables.BuildBrokenVendorPropertyNamespace 1678} 1679 1680func (c *deviceConfig) BuildBrokenInputDir(name string) bool { 1681 return InList(name, c.config.productVariables.BuildBrokenInputDirModules) 1682} 1683 1684func (c *deviceConfig) RequiresInsecureExecmemForSwiftshader() bool { 1685 return c.config.productVariables.RequiresInsecureExecmemForSwiftshader 1686} 1687 1688func (c *config) SelinuxIgnoreNeverallows() bool { 1689 return c.productVariables.SelinuxIgnoreNeverallows 1690} 1691 1692func (c *deviceConfig) SepolicySplit() bool { 1693 return c.config.productVariables.SepolicySplit 1694} 1695 1696func (c *deviceConfig) SepolicyFreezeTestExtraDirs() []string { 1697 return c.config.productVariables.SepolicyFreezeTestExtraDirs 1698} 1699 1700func (c *deviceConfig) SepolicyFreezeTestExtraPrebuiltDirs() []string { 1701 return c.config.productVariables.SepolicyFreezeTestExtraPrebuiltDirs 1702} 1703 1704func (c *deviceConfig) GenerateAidlNdkPlatformBackend() bool { 1705 return c.config.productVariables.GenerateAidlNdkPlatformBackend 1706} 1707 1708func (c *config) ForceMultilibFirstOnDevice() bool { 1709 return c.productVariables.ForceMultilibFirstOnDevice 1710} 1711 1712// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs. 1713// Such lists are used in the build system for things like bootclasspath jars or system server jars. 1714// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a 1715// module name. The pairs come from Make product variables as a list of colon-separated strings. 1716// 1717// Examples: 1718// - "com.android.art:core-oj" 1719// - "platform:framework" 1720// - "system_ext:foo" 1721// 1722type ConfiguredJarList struct { 1723 // A list of apex components, which can be an apex name, 1724 // or special names like "platform" or "system_ext". 1725 apexes []string 1726 1727 // A list of jar module name components. 1728 jars []string 1729} 1730 1731// Len returns the length of the list of jars. 1732func (l *ConfiguredJarList) Len() int { 1733 return len(l.jars) 1734} 1735 1736// Jar returns the idx-th jar component of (apex, jar) pairs. 1737func (l *ConfiguredJarList) Jar(idx int) string { 1738 return l.jars[idx] 1739} 1740 1741// Apex returns the idx-th apex component of (apex, jar) pairs. 1742func (l *ConfiguredJarList) Apex(idx int) string { 1743 return l.apexes[idx] 1744} 1745 1746// ContainsJar returns true if the (apex, jar) pairs contains a pair with the 1747// given jar module name. 1748func (l *ConfiguredJarList) ContainsJar(jar string) bool { 1749 return InList(jar, l.jars) 1750} 1751 1752// If the list contains the given (apex, jar) pair. 1753func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool { 1754 for i := 0; i < l.Len(); i++ { 1755 if apex == l.apexes[i] && jar == l.jars[i] { 1756 return true 1757 } 1758 } 1759 return false 1760} 1761 1762// ApexOfJar returns the apex component of the first pair with the given jar name on the list, or 1763// an empty string if not found. 1764func (l *ConfiguredJarList) ApexOfJar(jar string) string { 1765 if idx := IndexList(jar, l.jars); idx != -1 { 1766 return l.Apex(IndexList(jar, l.jars)) 1767 } 1768 return "" 1769} 1770 1771// IndexOfJar returns the first pair with the given jar name on the list, or -1 1772// if not found. 1773func (l *ConfiguredJarList) IndexOfJar(jar string) int { 1774 return IndexList(jar, l.jars) 1775} 1776 1777func copyAndAppend(list []string, item string) []string { 1778 // Create the result list to be 1 longer than the input. 1779 result := make([]string, len(list)+1) 1780 1781 // Copy the whole input list into the result. 1782 count := copy(result, list) 1783 1784 // Insert the extra item at the end. 1785 result[count] = item 1786 1787 return result 1788} 1789 1790// Append an (apex, jar) pair to the list. 1791func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList { 1792 // Create a copy of the backing arrays before appending to avoid sharing backing 1793 // arrays that are mutated across instances. 1794 apexes := copyAndAppend(l.apexes, apex) 1795 jars := copyAndAppend(l.jars, jar) 1796 1797 return ConfiguredJarList{apexes, jars} 1798} 1799 1800// Append a list of (apex, jar) pairs to the list. 1801func (l *ConfiguredJarList) AppendList(other *ConfiguredJarList) ConfiguredJarList { 1802 apexes := make([]string, 0, l.Len()+other.Len()) 1803 jars := make([]string, 0, l.Len()+other.Len()) 1804 1805 apexes = append(apexes, l.apexes...) 1806 jars = append(jars, l.jars...) 1807 1808 apexes = append(apexes, other.apexes...) 1809 jars = append(jars, other.jars...) 1810 1811 return ConfiguredJarList{apexes, jars} 1812} 1813 1814// RemoveList filters out a list of (apex, jar) pairs from the receiving list of pairs. 1815func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList { 1816 apexes := make([]string, 0, l.Len()) 1817 jars := make([]string, 0, l.Len()) 1818 1819 for i, jar := range l.jars { 1820 apex := l.apexes[i] 1821 if !list.containsApexJarPair(apex, jar) { 1822 apexes = append(apexes, apex) 1823 jars = append(jars, jar) 1824 } 1825 } 1826 1827 return ConfiguredJarList{apexes, jars} 1828} 1829 1830// Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list 1831// and any remaining jars that are not on this list. 1832func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) { 1833 var apexes []string 1834 var jars []string 1835 1836 for i, jar := range l.jars { 1837 if InList(jar, jarsToKeep) { 1838 apexes = append(apexes, l.apexes[i]) 1839 jars = append(jars, jar) 1840 } 1841 } 1842 1843 return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars) 1844} 1845 1846// CopyOfJars returns a copy of the list of strings containing jar module name 1847// components. 1848func (l *ConfiguredJarList) CopyOfJars() []string { 1849 return CopyOf(l.jars) 1850} 1851 1852// CopyOfApexJarPairs returns a copy of the list of strings with colon-separated 1853// (apex, jar) pairs. 1854func (l *ConfiguredJarList) CopyOfApexJarPairs() []string { 1855 pairs := make([]string, 0, l.Len()) 1856 1857 for i, jar := range l.jars { 1858 apex := l.apexes[i] 1859 pairs = append(pairs, apex+":"+jar) 1860 } 1861 1862 return pairs 1863} 1864 1865// BuildPaths returns a list of build paths based on the given directory prefix. 1866func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths { 1867 paths := make(WritablePaths, l.Len()) 1868 for i, jar := range l.jars { 1869 paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar") 1870 } 1871 return paths 1872} 1873 1874// BuildPathsByModule returns a map from module name to build paths based on the given directory 1875// prefix. 1876func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath { 1877 paths := map[string]WritablePath{} 1878 for _, jar := range l.jars { 1879 paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar") 1880 } 1881 return paths 1882} 1883 1884// UnmarshalJSON converts JSON configuration from raw bytes into a 1885// ConfiguredJarList structure. 1886func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error { 1887 // Try and unmarshal into a []string each item of which contains a pair 1888 // <apex>:<jar>. 1889 var list []string 1890 err := json.Unmarshal(b, &list) 1891 if err != nil { 1892 // Did not work so return 1893 return err 1894 } 1895 1896 apexes, jars, err := splitListOfPairsIntoPairOfLists(list) 1897 if err != nil { 1898 return err 1899 } 1900 l.apexes = apexes 1901 l.jars = jars 1902 return nil 1903} 1904 1905func (l *ConfiguredJarList) MarshalJSON() ([]byte, error) { 1906 if len(l.apexes) != len(l.jars) { 1907 return nil, errors.New(fmt.Sprintf("Inconsistent ConfiguredJarList: apexes: %q, jars: %q", l.apexes, l.jars)) 1908 } 1909 1910 list := make([]string, 0, len(l.apexes)) 1911 1912 for i := 0; i < len(l.apexes); i++ { 1913 list = append(list, l.apexes[i]+":"+l.jars[i]) 1914 } 1915 1916 return json.Marshal(list) 1917} 1918 1919// ModuleStem hardcodes the stem of framework-minus-apex to return "framework". 1920// 1921// TODO(b/139391334): hard coded until we find a good way to query the stem of a 1922// module before any other mutators are run. 1923func ModuleStem(module string) string { 1924 if module == "framework-minus-apex" { 1925 return "framework" 1926 } 1927 return module 1928} 1929 1930// DevicePaths computes the on-device paths for the list of (apex, jar) pairs, 1931// based on the operating system. 1932func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string { 1933 paths := make([]string, l.Len()) 1934 for i, jar := range l.jars { 1935 apex := l.apexes[i] 1936 name := ModuleStem(jar) + ".jar" 1937 1938 var subdir string 1939 if apex == "platform" { 1940 subdir = "system/framework" 1941 } else if apex == "system_ext" { 1942 subdir = "system_ext/framework" 1943 } else { 1944 subdir = filepath.Join("apex", apex, "javalib") 1945 } 1946 1947 if ostype.Class == Host { 1948 paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name) 1949 } else { 1950 paths[i] = filepath.Join("/", subdir, name) 1951 } 1952 } 1953 return paths 1954} 1955 1956func (l *ConfiguredJarList) String() string { 1957 var pairs []string 1958 for i := 0; i < l.Len(); i++ { 1959 pairs = append(pairs, l.apexes[i]+":"+l.jars[i]) 1960 } 1961 return strings.Join(pairs, ",") 1962} 1963 1964func splitListOfPairsIntoPairOfLists(list []string) ([]string, []string, error) { 1965 // Now we need to populate this list by splitting each item in the slice of 1966 // pairs and appending them to the appropriate list of apexes or jars. 1967 apexes := make([]string, len(list)) 1968 jars := make([]string, len(list)) 1969 1970 for i, apexjar := range list { 1971 apex, jar, err := splitConfiguredJarPair(apexjar) 1972 if err != nil { 1973 return nil, nil, err 1974 } 1975 apexes[i] = apex 1976 jars[i] = jar 1977 } 1978 1979 return apexes, jars, nil 1980} 1981 1982// Expected format for apexJarValue = <apex name>:<jar name> 1983func splitConfiguredJarPair(str string) (string, string, error) { 1984 pair := strings.SplitN(str, ":", 2) 1985 if len(pair) == 2 { 1986 apex := pair[0] 1987 jar := pair[1] 1988 if apex == "" { 1989 return apex, jar, fmt.Errorf("invalid apex '%s' in <apex>:<jar> pair '%s', expected format: <apex>:<jar>", apex, str) 1990 } 1991 return apex, jar, nil 1992 } else { 1993 return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str) 1994 } 1995} 1996 1997// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests. 1998func CreateTestConfiguredJarList(list []string) ConfiguredJarList { 1999 // Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to 2000 // a json list of strings and then unmarshalling into a ConfiguredJarList instance. 2001 b, err := json.Marshal(list) 2002 if err != nil { 2003 panic(err) 2004 } 2005 2006 var jarList ConfiguredJarList 2007 err = json.Unmarshal(b, &jarList) 2008 if err != nil { 2009 panic(err) 2010 } 2011 2012 return jarList 2013} 2014 2015// EmptyConfiguredJarList returns an empty jar list. 2016func EmptyConfiguredJarList() ConfiguredJarList { 2017 return ConfiguredJarList{} 2018} 2019 2020var earlyBootJarsKey = NewOnceKey("earlyBootJars") 2021 2022func (c *config) BootJars() []string { 2023 return c.Once(earlyBootJarsKey, func() interface{} { 2024 list := c.productVariables.BootJars.CopyOfJars() 2025 return append(list, c.productVariables.ApexBootJars.CopyOfJars()...) 2026 }).([]string) 2027} 2028 2029func (c *config) NonApexBootJars() ConfiguredJarList { 2030 return c.productVariables.BootJars 2031} 2032 2033func (c *config) ApexBootJars() ConfiguredJarList { 2034 return c.productVariables.ApexBootJars 2035} 2036 2037func (c *config) RBEWrapper() string { 2038 return c.GetenvWithDefault("RBE_WRAPPER", remoteexec.DefaultWrapperPath) 2039} 2040 2041// UseHostMusl returns true if the host target has been configured to build against musl libc. 2042func (c *config) UseHostMusl() bool { 2043 return Bool(c.productVariables.HostMusl) 2044} 2045