Merge "Add a prod var to override package names."
diff --git a/Android.bp b/Android.bp
index 62e276a..3215fa2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -71,6 +71,7 @@
"android/env.go",
],
testSrcs: [
+ "android/arch_test.go",
"android/config_test.go",
"android/expand_test.go",
"android/namespace_test.go",
diff --git a/android/arch.go b/android/arch.go
index de19dbe..6aeccb0 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -616,10 +616,10 @@
}
}
-func filterArchStructFields(fields []reflect.StructField) []reflect.StructField {
- var ret []reflect.StructField
+func filterArchStructFields(fields []reflect.StructField) (filteredFields []reflect.StructField, filtered bool) {
for _, field := range fields {
if !proptools.HasTag(field, "android", "arch_variant") {
+ filtered = true
continue
}
@@ -637,15 +637,17 @@
// Recurse into structs
switch field.Type.Kind() {
case reflect.Struct:
- var ok bool
- field.Type, ok = filterArchStruct(field.Type)
- if !ok {
+ var subFiltered bool
+ field.Type, subFiltered = filterArchStruct(field.Type)
+ filtered = filtered || subFiltered
+ if field.Type == nil {
continue
}
case reflect.Ptr:
if field.Type.Elem().Kind() == reflect.Struct {
- nestedType, ok := filterArchStruct(field.Type.Elem())
- if !ok {
+ nestedType, subFiltered := filterArchStruct(field.Type.Elem())
+ filtered = filtered || subFiltered
+ if nestedType == nil {
continue
}
field.Type = reflect.PtrTo(nestedType)
@@ -654,13 +656,17 @@
panic("Interfaces are not supported in arch_variant properties")
}
- ret = append(ret, field)
+ filteredFields = append(filteredFields, field)
}
- return ret
+ return filteredFields, filtered
}
-func filterArchStruct(prop reflect.Type) (reflect.Type, bool) {
+// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a reflect.Type
+// that only contains the fields in the original type that have an `android:"arch_variant"` struct tag, and a bool
+// that is true if the new struct type has fewer fields than the original type. If there are no fields in the
+// original type with the struct tag it returns nil and true.
+func filterArchStruct(prop reflect.Type) (filteredProp reflect.Type, filtered bool) {
var fields []reflect.StructField
ptr := prop.Kind() == reflect.Ptr
@@ -672,13 +678,20 @@
fields = append(fields, prop.Field(i))
}
- fields = filterArchStructFields(fields)
+ filteredFields, filtered := filterArchStructFields(fields)
- if len(fields) == 0 {
- return nil, false
+ if len(filteredFields) == 0 {
+ return nil, true
}
- ret := reflect.StructOf(fields)
+ if !filtered {
+ if ptr {
+ return reflect.PtrTo(prop), false
+ }
+ return prop, false
+ }
+
+ ret := reflect.StructOf(filteredFields)
if ptr {
ret = reflect.PtrTo(ret)
}
@@ -686,7 +699,13 @@
return ret, true
}
-func filterArchStructSharded(prop reflect.Type) ([]reflect.Type, bool) {
+// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a list of
+// reflect.Type that only contains the fields in the original type that have an `android:"arch_variant"` struct tag,
+// and a bool that is true if the new struct type has fewer fields than the original type. If there are no fields in
+// the original type with the struct tag it returns nil and true. Each returned struct type will have a maximum of
+// 10 top level fields in it to attempt to avoid hitting the reflect.StructOf name length limit, although the limit
+// can still be reached with a single struct field with many fields in it.
+func filterArchStructSharded(prop reflect.Type) (filteredProp []reflect.Type, filtered bool) {
var fields []reflect.StructField
ptr := prop.Kind() == reflect.Ptr
@@ -698,24 +717,29 @@
fields = append(fields, prop.Field(i))
}
- fields = filterArchStructFields(fields)
+ fields, filtered = filterArchStructFields(fields)
+ if !filtered {
+ if ptr {
+ return []reflect.Type{reflect.PtrTo(prop)}, false
+ }
+ return []reflect.Type{prop}, false
+ }
if len(fields) == 0 {
- return nil, false
+ return nil, true
}
shards := shardFields(fields, 10)
- var ret []reflect.Type
for _, shard := range shards {
s := reflect.StructOf(shard)
if ptr {
s = reflect.PtrTo(s)
}
- ret = append(ret, s)
+ filteredProp = append(filteredProp, s)
}
- return ret, true
+ return filteredProp, true
}
func shardFields(fields []reflect.StructField, shardSize int) [][]reflect.StructField {
@@ -730,9 +754,12 @@
return ret
}
+// createArchType takes a reflect.Type that is either a struct or a pointer to a struct, and returns a list of
+// reflect.Type that contains the arch-variant properties inside structs for each architecture, os, target, multilib,
+// etc.
func createArchType(props reflect.Type) []reflect.Type {
- propShards, ok := filterArchStructSharded(props)
- if !ok {
+ propShards, _ := filterArchStructSharded(props)
+ if len(propShards) == 0 {
return nil
}
diff --git a/android/arch_test.go b/android/arch_test.go
new file mode 100644
index 0000000..0589e6c
--- /dev/null
+++ b/android/arch_test.go
@@ -0,0 +1,232 @@
+// Copyright 2019 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 (
+ "reflect"
+ "testing"
+)
+
+type Named struct {
+ A *string `android:"arch_variant"`
+ B *string
+}
+
+type NamedAllFiltered struct {
+ A *string
+}
+
+type NamedNoneFiltered struct {
+ A *string `android:"arch_variant"`
+}
+
+func TestFilterArchStruct(t *testing.T) {
+ tests := []struct {
+ name string
+ in interface{}
+ out interface{}
+ filtered bool
+ }{
+ // Property tests
+ {
+ name: "basic",
+ in: &struct {
+ A *string `android:"arch_variant"`
+ B *string
+ }{},
+ out: &struct {
+ A *string
+ }{},
+ filtered: true,
+ },
+ {
+ name: "all filtered",
+ in: &struct {
+ A *string
+ }{},
+ out: nil,
+ filtered: true,
+ },
+ {
+ name: "none filtered",
+ in: &struct {
+ A *string `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A *string `android:"arch_variant"`
+ }{},
+ filtered: false,
+ },
+
+ // Sub-struct tests
+ {
+ name: "substruct",
+ in: &struct {
+ A struct {
+ A *string `android:"arch_variant"`
+ B *string
+ } `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A struct {
+ A *string
+ }
+ }{},
+ filtered: true,
+ },
+ {
+ name: "substruct all filtered",
+ in: &struct {
+ A struct {
+ A *string
+ } `android:"arch_variant"`
+ }{},
+ out: nil,
+ filtered: true,
+ },
+ {
+ name: "substruct none filtered",
+ in: &struct {
+ A struct {
+ A *string `android:"arch_variant"`
+ } `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A struct {
+ A *string `android:"arch_variant"`
+ } `android:"arch_variant"`
+ }{},
+ filtered: false,
+ },
+
+ // Named sub-struct tests
+ {
+ name: "named substruct",
+ in: &struct {
+ A Named `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A struct {
+ A *string
+ }
+ }{},
+ filtered: true,
+ },
+ {
+ name: "substruct all filtered",
+ in: &struct {
+ A NamedAllFiltered `android:"arch_variant"`
+ }{},
+ out: nil,
+ filtered: true,
+ },
+ {
+ name: "substruct none filtered",
+ in: &struct {
+ A NamedNoneFiltered `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A NamedNoneFiltered `android:"arch_variant"`
+ }{},
+ filtered: false,
+ },
+
+ // Pointer to sub-struct tests
+ {
+ name: "pointer substruct",
+ in: &struct {
+ A *struct {
+ A *string `android:"arch_variant"`
+ B *string
+ } `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A *struct {
+ A *string
+ }
+ }{},
+ filtered: true,
+ },
+ {
+ name: "pointer substruct all filtered",
+ in: &struct {
+ A *struct {
+ A *string
+ } `android:"arch_variant"`
+ }{},
+ out: nil,
+ filtered: true,
+ },
+ {
+ name: "pointer substruct none filtered",
+ in: &struct {
+ A *struct {
+ A *string `android:"arch_variant"`
+ } `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A *struct {
+ A *string `android:"arch_variant"`
+ } `android:"arch_variant"`
+ }{},
+ filtered: false,
+ },
+
+ // Pointer to named sub-struct tests
+ {
+ name: "pointer named substruct",
+ in: &struct {
+ A *Named `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A *struct {
+ A *string
+ }
+ }{},
+ filtered: true,
+ },
+ {
+ name: "pointer substruct all filtered",
+ in: &struct {
+ A *NamedAllFiltered `android:"arch_variant"`
+ }{},
+ out: nil,
+ filtered: true,
+ },
+ {
+ name: "pointer substruct none filtered",
+ in: &struct {
+ A *NamedNoneFiltered `android:"arch_variant"`
+ }{},
+ out: &struct {
+ A *NamedNoneFiltered `android:"arch_variant"`
+ }{},
+ filtered: false,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ out, filtered := filterArchStruct(reflect.TypeOf(test.in))
+ if filtered != test.filtered {
+ t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
+ }
+ expected := reflect.TypeOf(test.out)
+ if out != expected {
+ t.Errorf("expected type %v, got %v", expected, out)
+ }
+ })
+ }
+}
diff --git a/cc/library.go b/cc/library.go
index 09e5b50..ad07db4 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -29,27 +29,23 @@
"android/soong/genrule"
)
+type StaticSharedLibraryProperties struct {
+ Srcs []string `android:"arch_variant"`
+ Cflags []string `android:"arch_variant"`
+
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ System_shared_libs []string `android:"arch_variant"`
+
+ Export_shared_lib_headers []string `android:"arch_variant"`
+ Export_static_lib_headers []string `android:"arch_variant"`
+}
+
type LibraryProperties struct {
- Static struct {
- Srcs []string `android:"arch_variant"`
- Cflags []string `android:"arch_variant"`
-
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
- System_shared_libs []string `android:"arch_variant"`
- } `android:"arch_variant"`
- Shared struct {
- Srcs []string `android:"arch_variant"`
- Cflags []string `android:"arch_variant"`
-
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
- System_shared_libs []string `android:"arch_variant"`
- } `android:"arch_variant"`
+ Static StaticSharedLibraryProperties `android:"arch_variant"`
+ Shared StaticSharedLibraryProperties `android:"arch_variant"`
// local file name to pass to the linker as -unexported_symbols_list
Unexported_symbols_list *string `android:"arch_variant"`
@@ -539,6 +535,9 @@
library.Properties.Static.Whole_static_libs...)
deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
+
+ deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.Properties.Static.Export_shared_lib_headers...)
+ deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.Properties.Static.Export_static_lib_headers...)
} else if library.shared() {
if ctx.toolchain().Bionic() && !Bool(library.baseLinker.Properties.Nocrt) {
if !ctx.useSdk() {
@@ -560,6 +559,9 @@
deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
+
+ deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.Properties.Shared.Export_shared_lib_headers...)
+ deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.Properties.Shared.Export_static_lib_headers...)
}
if ctx.useVndk() {
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)