Merge changes I8a99e3d2,I717d7f5e
* changes: Remove unused bp2build logic from arch.go Split up config.go
This commit is contained in:
@@ -38,7 +38,9 @@ bootstrap_go_package {
|
||||
"bazel_paths.go",
|
||||
"buildinfo_prop.go",
|
||||
"config.go",
|
||||
"test_config.go",
|
||||
"config_bp2build.go",
|
||||
"configured_jars.go",
|
||||
"csuite_config.go",
|
||||
"deapexer.go",
|
||||
"defaults.go",
|
||||
|
@@ -393,54 +393,6 @@ func (target Target) Variations() []blueprint.Variation {
|
||||
}
|
||||
}
|
||||
|
||||
func registerBp2buildArchPathDepsMutator(ctx RegisterMutatorsContext) {
|
||||
ctx.BottomUp("bp2build-arch-pathdeps", bp2buildArchPathDepsMutator).Parallel()
|
||||
}
|
||||
|
||||
// add dependencies for architecture specific properties tagged with `android:"path"`
|
||||
func bp2buildArchPathDepsMutator(ctx BottomUpMutatorContext) {
|
||||
var module Module
|
||||
module = ctx.Module()
|
||||
|
||||
m := module.base()
|
||||
if !m.ArchSpecific() {
|
||||
return
|
||||
}
|
||||
|
||||
// addPathDepsForProps does not descend into sub structs, so we need to descend into the
|
||||
// arch-specific properties ourselves
|
||||
var properties []interface{}
|
||||
for _, archProperties := range m.archProperties {
|
||||
for _, archProps := range archProperties {
|
||||
archPropValues := reflect.ValueOf(archProps).Elem()
|
||||
// there are three "arch" variations, descend into each
|
||||
for _, variant := range []string{"Arch", "Multilib", "Target"} {
|
||||
// The properties are an interface, get the value (a pointer) that it points to
|
||||
archProps := archPropValues.FieldByName(variant).Elem()
|
||||
if archProps.IsNil() {
|
||||
continue
|
||||
}
|
||||
// And then a pointer to a struct
|
||||
archProps = archProps.Elem()
|
||||
for i := 0; i < archProps.NumField(); i += 1 {
|
||||
f := archProps.Field(i)
|
||||
// If the value of the field is a struct (as opposed to a pointer to a struct) then step
|
||||
// into the BlueprintEmbed field.
|
||||
if f.Kind() == reflect.Struct {
|
||||
f = f.FieldByName("BlueprintEmbed")
|
||||
}
|
||||
if f.IsZero() {
|
||||
continue
|
||||
}
|
||||
props := f.Interface().(interface{})
|
||||
properties = append(properties, props)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addPathDepsForProps(ctx, properties)
|
||||
}
|
||||
|
||||
// osMutator splits an arch-specific module into a variant for each OS that is enabled for the
|
||||
// module. It uses the HostOrDevice value passed to InitAndroidArchModule and the
|
||||
// device_supported and host_supported properties to determine which OsTypes are enabled for this
|
||||
@@ -998,19 +950,13 @@ func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.S
|
||||
if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` {
|
||||
panic(fmt.Errorf("unexpected tag format %q", field.Tag))
|
||||
}
|
||||
// don't delete path tag as it is needed for bp2build
|
||||
// these tags don't need to be present in the runtime generated struct type.
|
||||
values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend"})
|
||||
if len(values) > 0 && values[0] != "path" {
|
||||
values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
|
||||
if len(values) > 0 {
|
||||
panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
|
||||
} else if len(values) == 1 {
|
||||
// FIXME(b/200678898): This assumes that the only tag type when there's
|
||||
// `android:"arch_variant"` is `android` itself and thus clobbers others
|
||||
field.Tag = reflect.StructTag(`android:"` + strings.Join(values, ",") + `"`)
|
||||
} else {
|
||||
field.Tag = ``
|
||||
}
|
||||
|
||||
field.Tag = ``
|
||||
return true, field
|
||||
}
|
||||
return false, field
|
||||
|
@@ -66,9 +66,9 @@ func TestFilterArchStruct(t *testing.T) {
|
||||
}{},
|
||||
out: &struct {
|
||||
A *string
|
||||
B *string `android:"path"`
|
||||
C *string `android:"path"`
|
||||
D *string `android:"path"`
|
||||
B *string
|
||||
C *string
|
||||
D *string
|
||||
}{},
|
||||
filtered: true,
|
||||
},
|
||||
|
@@ -20,7 +20,6 @@ package android
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -345,123 +344,6 @@ func NullConfig(outDir, soongOutDir string) Config {
|
||||
}
|
||||
}
|
||||
|
||||
// TestConfig returns a Config object for testing.
|
||||
func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
|
||||
envCopy := make(map[string]string)
|
||||
for k, v := range env {
|
||||
envCopy[k] = v
|
||||
}
|
||||
|
||||
// Copy the real PATH value to the test environment, it's needed by
|
||||
// NonHermeticHostSystemTool() used in x86_darwin_host.go
|
||||
envCopy["PATH"] = os.Getenv("PATH")
|
||||
|
||||
config := &config{
|
||||
productVariables: productVariables{
|
||||
DeviceName: stringPtr("test_device"),
|
||||
DeviceProduct: stringPtr("test_product"),
|
||||
Platform_sdk_version: intPtr(30),
|
||||
Platform_sdk_codename: stringPtr("S"),
|
||||
Platform_base_sdk_extension_version: intPtr(1),
|
||||
Platform_version_active_codenames: []string{"S", "Tiramisu"},
|
||||
DeviceSystemSdkVersions: []string{"14", "15"},
|
||||
Platform_systemsdk_versions: []string{"29", "30"},
|
||||
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
|
||||
AAPTPreferredConfig: stringPtr("xhdpi"),
|
||||
AAPTCharacteristics: stringPtr("nosdcard"),
|
||||
AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
|
||||
UncompressPrivAppDex: boolPtr(true),
|
||||
ShippingApiLevel: stringPtr("30"),
|
||||
},
|
||||
|
||||
outDir: buildDir,
|
||||
soongOutDir: filepath.Join(buildDir, "soong"),
|
||||
captureBuild: true,
|
||||
env: envCopy,
|
||||
|
||||
// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
|
||||
// passed to PathForSource or PathForModuleSrc.
|
||||
TestAllowNonExistentPaths: true,
|
||||
|
||||
BazelContext: noopBazelContext{},
|
||||
mixedBuildDisabledModules: make(map[string]struct{}),
|
||||
mixedBuildEnabledModules: make(map[string]struct{}),
|
||||
}
|
||||
config.deviceConfig = &deviceConfig{
|
||||
config: config,
|
||||
}
|
||||
config.TestProductVariables = &config.productVariables
|
||||
|
||||
config.mockFileSystem(bp, fs)
|
||||
|
||||
determineBuildOS(config)
|
||||
|
||||
return Config{config}
|
||||
}
|
||||
|
||||
func modifyTestConfigToSupportArchMutator(testConfig Config) {
|
||||
config := testConfig.config
|
||||
|
||||
config.Targets = map[OsType][]Target{
|
||||
Android: []Target{
|
||||
{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
|
||||
{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
|
||||
},
|
||||
config.BuildOS: []Target{
|
||||
{config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
|
||||
{config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
|
||||
},
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1]
|
||||
}
|
||||
|
||||
config.BuildOSTarget = config.Targets[config.BuildOS][0]
|
||||
config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
|
||||
config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
|
||||
config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
|
||||
config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
|
||||
config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
|
||||
config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
|
||||
config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
|
||||
}
|
||||
|
||||
func modifyTestConfigForMusl(config Config) {
|
||||
delete(config.Targets, config.BuildOS)
|
||||
config.productVariables.HostMusl = boolPtr(true)
|
||||
determineBuildOS(config.config)
|
||||
config.Targets[config.BuildOS] = []Target{
|
||||
{config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
|
||||
{config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
|
||||
}
|
||||
|
||||
config.BuildOSTarget = config.Targets[config.BuildOS][0]
|
||||
config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
|
||||
}
|
||||
|
||||
// TestArchConfig returns a Config object suitable for using for tests that
|
||||
// need to run the arch mutator.
|
||||
func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
|
||||
testConfig := TestConfig(buildDir, env, bp, fs)
|
||||
modifyTestConfigToSupportArchMutator(testConfig)
|
||||
return testConfig
|
||||
}
|
||||
|
||||
// ConfigForAdditionalRun is a config object which is "reset" for another
|
||||
// bootstrap run. Only per-run data is reset. Data which needs to persist across
|
||||
// multiple runs in the same program execution is carried over (such as Bazel
|
||||
// context or environment deps).
|
||||
func ConfigForAdditionalRun(c Config) (Config, error) {
|
||||
newConfig, err := NewConfig(c.moduleListFile, c.runGoTests, c.outDir, c.soongOutDir, c.env)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
newConfig.BazelContext = c.BazelContext
|
||||
newConfig.envDeps = c.envDeps
|
||||
return newConfig, nil
|
||||
}
|
||||
|
||||
// NewConfig creates a new Config object. The srcDir argument specifies the path
|
||||
// to the root source directory. It also loads the config file, if found.
|
||||
func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) {
|
||||
@@ -744,7 +626,8 @@ func (c *config) DeviceName() string {
|
||||
// these per device type.
|
||||
//
|
||||
// NOTE: Do not base conditional logic on this value. It may break product
|
||||
// inheritance.
|
||||
//
|
||||
// inheritance.
|
||||
func (c *config) DeviceProduct() string {
|
||||
return *c.productVariables.DeviceProduct
|
||||
}
|
||||
@@ -1737,316 +1620,6 @@ func (c *config) IgnorePrefer32OnDevice() bool {
|
||||
return c.productVariables.IgnorePrefer32OnDevice
|
||||
}
|
||||
|
||||
// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
|
||||
// Such lists are used in the build system for things like bootclasspath jars or system server jars.
|
||||
// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
|
||||
// module name. The pairs come from Make product variables as a list of colon-separated strings.
|
||||
//
|
||||
// Examples:
|
||||
// - "com.android.art:core-oj"
|
||||
// - "platform:framework"
|
||||
// - "system_ext:foo"
|
||||
//
|
||||
type ConfiguredJarList struct {
|
||||
// A list of apex components, which can be an apex name,
|
||||
// or special names like "platform" or "system_ext".
|
||||
apexes []string
|
||||
|
||||
// A list of jar module name components.
|
||||
jars []string
|
||||
}
|
||||
|
||||
// Len returns the length of the list of jars.
|
||||
func (l *ConfiguredJarList) Len() int {
|
||||
return len(l.jars)
|
||||
}
|
||||
|
||||
// Jar returns the idx-th jar component of (apex, jar) pairs.
|
||||
func (l *ConfiguredJarList) Jar(idx int) string {
|
||||
return l.jars[idx]
|
||||
}
|
||||
|
||||
// Apex returns the idx-th apex component of (apex, jar) pairs.
|
||||
func (l *ConfiguredJarList) Apex(idx int) string {
|
||||
return l.apexes[idx]
|
||||
}
|
||||
|
||||
// ContainsJar returns true if the (apex, jar) pairs contains a pair with the
|
||||
// given jar module name.
|
||||
func (l *ConfiguredJarList) ContainsJar(jar string) bool {
|
||||
return InList(jar, l.jars)
|
||||
}
|
||||
|
||||
// If the list contains the given (apex, jar) pair.
|
||||
func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool {
|
||||
for i := 0; i < l.Len(); i++ {
|
||||
if apex == l.apexes[i] && jar == l.jars[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ApexOfJar returns the apex component of the first pair with the given jar name on the list, or
|
||||
// an empty string if not found.
|
||||
func (l *ConfiguredJarList) ApexOfJar(jar string) string {
|
||||
if idx := IndexList(jar, l.jars); idx != -1 {
|
||||
return l.Apex(IndexList(jar, l.jars))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// IndexOfJar returns the first pair with the given jar name on the list, or -1
|
||||
// if not found.
|
||||
func (l *ConfiguredJarList) IndexOfJar(jar string) int {
|
||||
return IndexList(jar, l.jars)
|
||||
}
|
||||
|
||||
func copyAndAppend(list []string, item string) []string {
|
||||
// Create the result list to be 1 longer than the input.
|
||||
result := make([]string, len(list)+1)
|
||||
|
||||
// Copy the whole input list into the result.
|
||||
count := copy(result, list)
|
||||
|
||||
// Insert the extra item at the end.
|
||||
result[count] = item
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Append an (apex, jar) pair to the list.
|
||||
func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList {
|
||||
// Create a copy of the backing arrays before appending to avoid sharing backing
|
||||
// arrays that are mutated across instances.
|
||||
apexes := copyAndAppend(l.apexes, apex)
|
||||
jars := copyAndAppend(l.jars, jar)
|
||||
|
||||
return ConfiguredJarList{apexes, jars}
|
||||
}
|
||||
|
||||
// Append a list of (apex, jar) pairs to the list.
|
||||
func (l *ConfiguredJarList) AppendList(other *ConfiguredJarList) ConfiguredJarList {
|
||||
apexes := make([]string, 0, l.Len()+other.Len())
|
||||
jars := make([]string, 0, l.Len()+other.Len())
|
||||
|
||||
apexes = append(apexes, l.apexes...)
|
||||
jars = append(jars, l.jars...)
|
||||
|
||||
apexes = append(apexes, other.apexes...)
|
||||
jars = append(jars, other.jars...)
|
||||
|
||||
return ConfiguredJarList{apexes, jars}
|
||||
}
|
||||
|
||||
// RemoveList filters out a list of (apex, jar) pairs from the receiving list of pairs.
|
||||
func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
|
||||
apexes := make([]string, 0, l.Len())
|
||||
jars := make([]string, 0, l.Len())
|
||||
|
||||
for i, jar := range l.jars {
|
||||
apex := l.apexes[i]
|
||||
if !list.containsApexJarPair(apex, jar) {
|
||||
apexes = append(apexes, apex)
|
||||
jars = append(jars, jar)
|
||||
}
|
||||
}
|
||||
|
||||
return ConfiguredJarList{apexes, jars}
|
||||
}
|
||||
|
||||
// Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list
|
||||
// and any remaining jars that are not on this list.
|
||||
func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) {
|
||||
var apexes []string
|
||||
var jars []string
|
||||
|
||||
for i, jar := range l.jars {
|
||||
if InList(jar, jarsToKeep) {
|
||||
apexes = append(apexes, l.apexes[i])
|
||||
jars = append(jars, jar)
|
||||
}
|
||||
}
|
||||
|
||||
return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars)
|
||||
}
|
||||
|
||||
// CopyOfJars returns a copy of the list of strings containing jar module name
|
||||
// components.
|
||||
func (l *ConfiguredJarList) CopyOfJars() []string {
|
||||
return CopyOf(l.jars)
|
||||
}
|
||||
|
||||
// CopyOfApexJarPairs returns a copy of the list of strings with colon-separated
|
||||
// (apex, jar) pairs.
|
||||
func (l *ConfiguredJarList) CopyOfApexJarPairs() []string {
|
||||
pairs := make([]string, 0, l.Len())
|
||||
|
||||
for i, jar := range l.jars {
|
||||
apex := l.apexes[i]
|
||||
pairs = append(pairs, apex+":"+jar)
|
||||
}
|
||||
|
||||
return pairs
|
||||
}
|
||||
|
||||
// BuildPaths returns a list of build paths based on the given directory prefix.
|
||||
func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths {
|
||||
paths := make(WritablePaths, l.Len())
|
||||
for i, jar := range l.jars {
|
||||
paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar")
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
// BuildPathsByModule returns a map from module name to build paths based on the given directory
|
||||
// prefix.
|
||||
func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
|
||||
paths := map[string]WritablePath{}
|
||||
for _, jar := range l.jars {
|
||||
paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
// UnmarshalJSON converts JSON configuration from raw bytes into a
|
||||
// ConfiguredJarList structure.
|
||||
func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error {
|
||||
// Try and unmarshal into a []string each item of which contains a pair
|
||||
// <apex>:<jar>.
|
||||
var list []string
|
||||
err := json.Unmarshal(b, &list)
|
||||
if err != nil {
|
||||
// Did not work so return
|
||||
return err
|
||||
}
|
||||
|
||||
apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.apexes = apexes
|
||||
l.jars = jars
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *ConfiguredJarList) MarshalJSON() ([]byte, error) {
|
||||
if len(l.apexes) != len(l.jars) {
|
||||
return nil, errors.New(fmt.Sprintf("Inconsistent ConfiguredJarList: apexes: %q, jars: %q", l.apexes, l.jars))
|
||||
}
|
||||
|
||||
list := make([]string, 0, len(l.apexes))
|
||||
|
||||
for i := 0; i < len(l.apexes); i++ {
|
||||
list = append(list, l.apexes[i]+":"+l.jars[i])
|
||||
}
|
||||
|
||||
return json.Marshal(list)
|
||||
}
|
||||
|
||||
// ModuleStem hardcodes the stem of framework-minus-apex to return "framework".
|
||||
//
|
||||
// TODO(b/139391334): hard coded until we find a good way to query the stem of a
|
||||
// module before any other mutators are run.
|
||||
func ModuleStem(module string) string {
|
||||
if module == "framework-minus-apex" {
|
||||
return "framework"
|
||||
}
|
||||
return module
|
||||
}
|
||||
|
||||
// DevicePaths computes the on-device paths for the list of (apex, jar) pairs,
|
||||
// based on the operating system.
|
||||
func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string {
|
||||
paths := make([]string, l.Len())
|
||||
for i, jar := range l.jars {
|
||||
apex := l.apexes[i]
|
||||
name := ModuleStem(jar) + ".jar"
|
||||
|
||||
var subdir string
|
||||
if apex == "platform" {
|
||||
subdir = "system/framework"
|
||||
} else if apex == "system_ext" {
|
||||
subdir = "system_ext/framework"
|
||||
} else {
|
||||
subdir = filepath.Join("apex", apex, "javalib")
|
||||
}
|
||||
|
||||
if ostype.Class == Host {
|
||||
paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name)
|
||||
} else {
|
||||
paths[i] = filepath.Join("/", subdir, name)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (l *ConfiguredJarList) String() string {
|
||||
var pairs []string
|
||||
for i := 0; i < l.Len(); i++ {
|
||||
pairs = append(pairs, l.apexes[i]+":"+l.jars[i])
|
||||
}
|
||||
return strings.Join(pairs, ",")
|
||||
}
|
||||
|
||||
func splitListOfPairsIntoPairOfLists(list []string) ([]string, []string, error) {
|
||||
// Now we need to populate this list by splitting each item in the slice of
|
||||
// pairs and appending them to the appropriate list of apexes or jars.
|
||||
apexes := make([]string, len(list))
|
||||
jars := make([]string, len(list))
|
||||
|
||||
for i, apexjar := range list {
|
||||
apex, jar, err := splitConfiguredJarPair(apexjar)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
apexes[i] = apex
|
||||
jars[i] = jar
|
||||
}
|
||||
|
||||
return apexes, jars, nil
|
||||
}
|
||||
|
||||
// Expected format for apexJarValue = <apex name>:<jar name>
|
||||
func splitConfiguredJarPair(str string) (string, string, error) {
|
||||
pair := strings.SplitN(str, ":", 2)
|
||||
if len(pair) == 2 {
|
||||
apex := pair[0]
|
||||
jar := pair[1]
|
||||
if apex == "" {
|
||||
return apex, jar, fmt.Errorf("invalid apex '%s' in <apex>:<jar> pair '%s', expected format: <apex>:<jar>", apex, str)
|
||||
}
|
||||
return apex, jar, nil
|
||||
} else {
|
||||
return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests.
|
||||
func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
|
||||
// Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to
|
||||
// a json list of strings and then unmarshalling into a ConfiguredJarList instance.
|
||||
b, err := json.Marshal(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var jarList ConfiguredJarList
|
||||
err = json.Unmarshal(b, &jarList)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return jarList
|
||||
}
|
||||
|
||||
// EmptyConfiguredJarList returns an empty jar list.
|
||||
func EmptyConfiguredJarList() ConfiguredJarList {
|
||||
return ConfiguredJarList{}
|
||||
}
|
||||
|
||||
var earlyBootJarsKey = NewOnceKey("earlyBootJars")
|
||||
|
||||
func (c *config) BootJars() []string {
|
||||
return c.Once(earlyBootJarsKey, func() interface{} {
|
||||
list := c.productVariables.BootJars.CopyOfJars()
|
||||
|
314
android/configured_jars.go
Normal file
314
android/configured_jars.go
Normal file
@@ -0,0 +1,314 @@
|
||||
// Copyright 2022 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package android
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
|
||||
// Such lists are used in the build system for things like bootclasspath jars or system server jars.
|
||||
// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
|
||||
// module name. The pairs come from Make product variables as a list of colon-separated strings.
|
||||
//
|
||||
// Examples:
|
||||
// - "com.android.art:core-oj"
|
||||
// - "platform:framework"
|
||||
// - "system_ext:foo"
|
||||
type ConfiguredJarList struct {
|
||||
// A list of apex components, which can be an apex name,
|
||||
// or special names like "platform" or "system_ext".
|
||||
apexes []string
|
||||
|
||||
// A list of jar module name components.
|
||||
jars []string
|
||||
}
|
||||
|
||||
// Len returns the length of the list of jars.
|
||||
func (l *ConfiguredJarList) Len() int {
|
||||
return len(l.jars)
|
||||
}
|
||||
|
||||
// Jar returns the idx-th jar component of (apex, jar) pairs.
|
||||
func (l *ConfiguredJarList) Jar(idx int) string {
|
||||
return l.jars[idx]
|
||||
}
|
||||
|
||||
// Apex returns the idx-th apex component of (apex, jar) pairs.
|
||||
func (l *ConfiguredJarList) Apex(idx int) string {
|
||||
return l.apexes[idx]
|
||||
}
|
||||
|
||||
// ContainsJar returns true if the (apex, jar) pairs contains a pair with the
|
||||
// given jar module name.
|
||||
func (l *ConfiguredJarList) ContainsJar(jar string) bool {
|
||||
return InList(jar, l.jars)
|
||||
}
|
||||
|
||||
// If the list contains the given (apex, jar) pair.
|
||||
func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool {
|
||||
for i := 0; i < l.Len(); i++ {
|
||||
if apex == l.apexes[i] && jar == l.jars[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ApexOfJar returns the apex component of the first pair with the given jar name on the list, or
|
||||
// an empty string if not found.
|
||||
func (l *ConfiguredJarList) ApexOfJar(jar string) string {
|
||||
if idx := IndexList(jar, l.jars); idx != -1 {
|
||||
return l.Apex(IndexList(jar, l.jars))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// IndexOfJar returns the first pair with the given jar name on the list, or -1
|
||||
// if not found.
|
||||
func (l *ConfiguredJarList) IndexOfJar(jar string) int {
|
||||
return IndexList(jar, l.jars)
|
||||
}
|
||||
|
||||
func copyAndAppend(list []string, item string) []string {
|
||||
// Create the result list to be 1 longer than the input.
|
||||
result := make([]string, len(list)+1)
|
||||
|
||||
// Copy the whole input list into the result.
|
||||
count := copy(result, list)
|
||||
|
||||
// Insert the extra item at the end.
|
||||
result[count] = item
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Append an (apex, jar) pair to the list.
|
||||
func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList {
|
||||
// Create a copy of the backing arrays before appending to avoid sharing backing
|
||||
// arrays that are mutated across instances.
|
||||
apexes := copyAndAppend(l.apexes, apex)
|
||||
jars := copyAndAppend(l.jars, jar)
|
||||
|
||||
return ConfiguredJarList{apexes, jars}
|
||||
}
|
||||
|
||||
// Append a list of (apex, jar) pairs to the list.
|
||||
func (l *ConfiguredJarList) AppendList(other *ConfiguredJarList) ConfiguredJarList {
|
||||
apexes := make([]string, 0, l.Len()+other.Len())
|
||||
jars := make([]string, 0, l.Len()+other.Len())
|
||||
|
||||
apexes = append(apexes, l.apexes...)
|
||||
jars = append(jars, l.jars...)
|
||||
|
||||
apexes = append(apexes, other.apexes...)
|
||||
jars = append(jars, other.jars...)
|
||||
|
||||
return ConfiguredJarList{apexes, jars}
|
||||
}
|
||||
|
||||
// RemoveList filters out a list of (apex, jar) pairs from the receiving list of pairs.
|
||||
func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
|
||||
apexes := make([]string, 0, l.Len())
|
||||
jars := make([]string, 0, l.Len())
|
||||
|
||||
for i, jar := range l.jars {
|
||||
apex := l.apexes[i]
|
||||
if !list.containsApexJarPair(apex, jar) {
|
||||
apexes = append(apexes, apex)
|
||||
jars = append(jars, jar)
|
||||
}
|
||||
}
|
||||
|
||||
return ConfiguredJarList{apexes, jars}
|
||||
}
|
||||
|
||||
// Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list
|
||||
// and any remaining jars that are not on this list.
|
||||
func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) {
|
||||
var apexes []string
|
||||
var jars []string
|
||||
|
||||
for i, jar := range l.jars {
|
||||
if InList(jar, jarsToKeep) {
|
||||
apexes = append(apexes, l.apexes[i])
|
||||
jars = append(jars, jar)
|
||||
}
|
||||
}
|
||||
|
||||
return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars)
|
||||
}
|
||||
|
||||
// CopyOfJars returns a copy of the list of strings containing jar module name
|
||||
// components.
|
||||
func (l *ConfiguredJarList) CopyOfJars() []string {
|
||||
return CopyOf(l.jars)
|
||||
}
|
||||
|
||||
// CopyOfApexJarPairs returns a copy of the list of strings with colon-separated
|
||||
// (apex, jar) pairs.
|
||||
func (l *ConfiguredJarList) CopyOfApexJarPairs() []string {
|
||||
pairs := make([]string, 0, l.Len())
|
||||
|
||||
for i, jar := range l.jars {
|
||||
apex := l.apexes[i]
|
||||
pairs = append(pairs, apex+":"+jar)
|
||||
}
|
||||
|
||||
return pairs
|
||||
}
|
||||
|
||||
// BuildPaths returns a list of build paths based on the given directory prefix.
|
||||
func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths {
|
||||
paths := make(WritablePaths, l.Len())
|
||||
for i, jar := range l.jars {
|
||||
paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar")
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
// BuildPathsByModule returns a map from module name to build paths based on the given directory
|
||||
// prefix.
|
||||
func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
|
||||
paths := map[string]WritablePath{}
|
||||
for _, jar := range l.jars {
|
||||
paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
// UnmarshalJSON converts JSON configuration from raw bytes into a
|
||||
// ConfiguredJarList structure.
|
||||
func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error {
|
||||
// Try and unmarshal into a []string each item of which contains a pair
|
||||
// <apex>:<jar>.
|
||||
var list []string
|
||||
err := json.Unmarshal(b, &list)
|
||||
if err != nil {
|
||||
// Did not work so return
|
||||
return err
|
||||
}
|
||||
|
||||
apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.apexes = apexes
|
||||
l.jars = jars
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *ConfiguredJarList) MarshalJSON() ([]byte, error) {
|
||||
if len(l.apexes) != len(l.jars) {
|
||||
return nil, errors.New(fmt.Sprintf("Inconsistent ConfiguredJarList: apexes: %q, jars: %q", l.apexes, l.jars))
|
||||
}
|
||||
|
||||
list := make([]string, 0, len(l.apexes))
|
||||
|
||||
for i := 0; i < len(l.apexes); i++ {
|
||||
list = append(list, l.apexes[i]+":"+l.jars[i])
|
||||
}
|
||||
|
||||
return json.Marshal(list)
|
||||
}
|
||||
|
||||
// ModuleStem hardcodes the stem of framework-minus-apex to return "framework".
|
||||
//
|
||||
// TODO(b/139391334): hard coded until we find a good way to query the stem of a
|
||||
// module before any other mutators are run.
|
||||
func ModuleStem(module string) string {
|
||||
if module == "framework-minus-apex" {
|
||||
return "framework"
|
||||
}
|
||||
return module
|
||||
}
|
||||
|
||||
// DevicePaths computes the on-device paths for the list of (apex, jar) pairs,
|
||||
// based on the operating system.
|
||||
func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string {
|
||||
paths := make([]string, l.Len())
|
||||
for i, jar := range l.jars {
|
||||
apex := l.apexes[i]
|
||||
name := ModuleStem(jar) + ".jar"
|
||||
|
||||
var subdir string
|
||||
if apex == "platform" {
|
||||
subdir = "system/framework"
|
||||
} else if apex == "system_ext" {
|
||||
subdir = "system_ext/framework"
|
||||
} else {
|
||||
subdir = filepath.Join("apex", apex, "javalib")
|
||||
}
|
||||
|
||||
if ostype.Class == Host {
|
||||
paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name)
|
||||
} else {
|
||||
paths[i] = filepath.Join("/", subdir, name)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (l *ConfiguredJarList) String() string {
|
||||
var pairs []string
|
||||
for i := 0; i < l.Len(); i++ {
|
||||
pairs = append(pairs, l.apexes[i]+":"+l.jars[i])
|
||||
}
|
||||
return strings.Join(pairs, ",")
|
||||
}
|
||||
|
||||
func splitListOfPairsIntoPairOfLists(list []string) ([]string, []string, error) {
|
||||
// Now we need to populate this list by splitting each item in the slice of
|
||||
// pairs and appending them to the appropriate list of apexes or jars.
|
||||
apexes := make([]string, len(list))
|
||||
jars := make([]string, len(list))
|
||||
|
||||
for i, apexjar := range list {
|
||||
apex, jar, err := splitConfiguredJarPair(apexjar)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
apexes[i] = apex
|
||||
jars[i] = jar
|
||||
}
|
||||
|
||||
return apexes, jars, nil
|
||||
}
|
||||
|
||||
// Expected format for apexJarValue = <apex name>:<jar name>
|
||||
func splitConfiguredJarPair(str string) (string, string, error) {
|
||||
pair := strings.SplitN(str, ":", 2)
|
||||
if len(pair) == 2 {
|
||||
apex := pair[0]
|
||||
jar := pair[1]
|
||||
if apex == "" {
|
||||
return apex, jar, fmt.Errorf("invalid apex '%s' in <apex>:<jar> pair '%s', expected format: <apex>:<jar>", apex, str)
|
||||
}
|
||||
return apex, jar, nil
|
||||
} else {
|
||||
return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
|
||||
}
|
||||
}
|
||||
|
||||
// EmptyConfiguredJarList returns an empty jar list.
|
||||
func EmptyConfiguredJarList() ConfiguredJarList {
|
||||
return ConfiguredJarList{}
|
||||
}
|
||||
|
||||
var earlyBootJarsKey = NewOnceKey("earlyBootJars")
|
145
android/test_config.go
Normal file
145
android/test_config.go
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright 2022 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package android
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
// TestConfig returns a Config object for testing.
|
||||
func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
|
||||
envCopy := make(map[string]string)
|
||||
for k, v := range env {
|
||||
envCopy[k] = v
|
||||
}
|
||||
|
||||
// Copy the real PATH value to the test environment, it's needed by
|
||||
// NonHermeticHostSystemTool() used in x86_darwin_host.go
|
||||
envCopy["PATH"] = os.Getenv("PATH")
|
||||
|
||||
config := &config{
|
||||
productVariables: productVariables{
|
||||
DeviceName: stringPtr("test_device"),
|
||||
DeviceProduct: stringPtr("test_product"),
|
||||
Platform_sdk_version: intPtr(30),
|
||||
Platform_sdk_codename: stringPtr("S"),
|
||||
Platform_base_sdk_extension_version: intPtr(1),
|
||||
Platform_version_active_codenames: []string{"S", "Tiramisu"},
|
||||
DeviceSystemSdkVersions: []string{"14", "15"},
|
||||
Platform_systemsdk_versions: []string{"29", "30"},
|
||||
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
|
||||
AAPTPreferredConfig: stringPtr("xhdpi"),
|
||||
AAPTCharacteristics: stringPtr("nosdcard"),
|
||||
AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
|
||||
UncompressPrivAppDex: boolPtr(true),
|
||||
ShippingApiLevel: stringPtr("30"),
|
||||
},
|
||||
|
||||
outDir: buildDir,
|
||||
soongOutDir: filepath.Join(buildDir, "soong"),
|
||||
captureBuild: true,
|
||||
env: envCopy,
|
||||
|
||||
// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
|
||||
// passed to PathForSource or PathForModuleSrc.
|
||||
TestAllowNonExistentPaths: true,
|
||||
|
||||
BazelContext: noopBazelContext{},
|
||||
mixedBuildDisabledModules: make(map[string]struct{}),
|
||||
mixedBuildEnabledModules: make(map[string]struct{}),
|
||||
}
|
||||
config.deviceConfig = &deviceConfig{
|
||||
config: config,
|
||||
}
|
||||
config.TestProductVariables = &config.productVariables
|
||||
|
||||
config.mockFileSystem(bp, fs)
|
||||
|
||||
determineBuildOS(config)
|
||||
|
||||
return Config{config}
|
||||
}
|
||||
|
||||
func modifyTestConfigToSupportArchMutator(testConfig Config) {
|
||||
config := testConfig.config
|
||||
|
||||
config.Targets = map[OsType][]Target{
|
||||
Android: []Target{
|
||||
{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
|
||||
{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
|
||||
},
|
||||
config.BuildOS: []Target{
|
||||
{config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
|
||||
{config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
|
||||
},
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1]
|
||||
}
|
||||
|
||||
config.BuildOSTarget = config.Targets[config.BuildOS][0]
|
||||
config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
|
||||
config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
|
||||
config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
|
||||
config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
|
||||
config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
|
||||
config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
|
||||
config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
|
||||
}
|
||||
|
||||
func modifyTestConfigForMusl(config Config) {
|
||||
delete(config.Targets, config.BuildOS)
|
||||
config.productVariables.HostMusl = boolPtr(true)
|
||||
determineBuildOS(config.config)
|
||||
config.Targets[config.BuildOS] = []Target{
|
||||
{config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
|
||||
{config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
|
||||
}
|
||||
|
||||
config.BuildOSTarget = config.Targets[config.BuildOS][0]
|
||||
config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
|
||||
}
|
||||
|
||||
// TestArchConfig returns a Config object suitable for using for tests that
|
||||
// need to run the arch mutator.
|
||||
func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
|
||||
testConfig := TestConfig(buildDir, env, bp, fs)
|
||||
modifyTestConfigToSupportArchMutator(testConfig)
|
||||
return testConfig
|
||||
}
|
||||
|
||||
// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests.
|
||||
func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
|
||||
// Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to
|
||||
// a json list of strings and then unmarshalling into a ConfiguredJarList instance.
|
||||
b, err := json.Marshal(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var jarList ConfiguredJarList
|
||||
err = json.Unmarshal(b, &jarList)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return jarList
|
||||
}
|
Reference in New Issue
Block a user