Merge "Shard rust protobuf sources" into main
diff --git a/.gitignore b/.gitignore
index 5d2bc0d..89de74e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
*.iml
*.ipr
*.iws
-
+*.swp
+/.vscode
diff --git a/README.md b/README.md
index 93260e6..140822b 100644
--- a/README.md
+++ b/README.md
@@ -449,6 +449,7 @@
config_namespace: "acme",
variables: ["board"],
bool_variables: ["feature"],
+ list_variables: ["impl"],
value_variables: ["width"],
properties: ["cflags", "srcs"],
}
@@ -460,24 +461,40 @@
```
This example describes a new `acme_cc_defaults` module type that extends the
-`cc_defaults` module type, with three additional conditionals based on
-variables `board`, `feature` and `width`, which can affect properties `cflags`
-and `srcs`. Additionally, each conditional will contain a `conditions_default`
-property can affect `cflags` and `srcs` in the following conditions:
+`cc_defaults` module type, with four additional conditionals based on variables
+`board`, `feature`, `impl` and `width` which can affect properties `cflags` and
+`srcs`. The four types of soong variables control properties in the following
+ways.
-* bool variable (e.g. `feature`): the variable is unspecified or not set to a true value
+* bool variable (e.g. `feature`): Properties are applied if set to `true`.
+* list variable (e.g. `impl`): (lists of strings properties only) Properties are
+ applied for each value in the list, using `%s` substitution. For example, if
+ the property is `["%s.cpp", "%s.h"]` and the list value is `foo bar`,
+ the result is `["foo.cpp", "foo.h", "bar.cpp", "bar.h"]`.
+* value variable (e.g. `width`): (strings or lists of strings) The value are
+ directly substituted into properties using `%s`.
+* string variable (e.g. `board`): Properties are applied only if they match the
+ variable's value.
+
+Additionally, each conditional containing a `conditions_default` property can
+affect `cflags` and `srcs` in the following conditions:
+
+* bool variable (e.g. `feature`): the variable is unspecified or not set to
+ `true`
+* list variable (e.g. `impl`): the variable is unspecified
* value variable (e.g. `width`): the variable is unspecified
-* string variable (e.g. `board`): the variable is unspecified or the variable is set to a string unused in the
-given module. For example, with `board`, if the `board`
-conditional contains the properties `soc_a` and `conditions_default`, when
-board=soc_b, the `cflags` and `srcs` values under `conditions_default` will be
-used. To specify that no properties should be amended for `soc_b`, you can set
-`soc_b: {},`.
+* string variable (e.g. `board`): the variable is unspecified or the variable is
+ set to a string unused in the given module. For example, with `board`, if the
+ `board` conditional contains the properties `soc_a` and `conditions_default`,
+ when `board` is `soc_b`, the `cflags` and `srcs` values under
+ `conditions_default` is used. To specify that no properties should be amended
+ for `soc_b`, you can set `soc_b: {},`.
The values of the variables can be set from a product's `BoardConfig.mk` file:
```
$(call soong_config_set,acme,board,soc_a)
$(call soong_config_set,acme,feature,true)
+$(call soong_config_set,acme,impl,foo.cpp bar.cpp)
$(call soong_config_set,acme,width,200)
```
@@ -519,6 +536,12 @@
cflags: ["-DWIDTH=DEFAULT"],
},
},
+ impl: {
+ srcs: ["impl/%s"],
+ conditions_default: {
+ srcs: ["impl/default.cpp"],
+ },
+ },
},
}
@@ -530,7 +553,8 @@
```
With the `BoardConfig.mk` snippet above, `libacme_foo` would build with
-`cflags: "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200"`.
+`cflags: "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200"` and
+`srcs: ["*.cpp", "impl/foo.cpp", "impl/bar.cpp"]`.
Alternatively, with `DefaultBoardConfig.mk`:
@@ -539,12 +563,14 @@
SOONG_CONFIG_acme += \
board \
feature \
+ impl \
width \
SOONG_CONFIG_acme_feature := false
```
-then `libacme_foo` would build with `cflags: "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT"`.
+then `libacme_foo` would build with `cflags: "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT"`
+and `srcs: ["*.cpp", "impl/default.cpp"]`.
Alternatively, with `DefaultBoardConfig.mk`:
@@ -553,13 +579,15 @@
SOONG_CONFIG_acme += \
board \
feature \
+ impl \
width \
SOONG_CONFIG_acme_board := soc_c
+SOONG_CONFIG_acme_impl := baz
```
then `libacme_foo` would build with `cflags: "-DGENERIC -DSOC_DEFAULT
--DFEATURE_DEFAULT -DSIZE=DEFAULT"`.
+-DFEATURE_DEFAULT -DSIZE=DEFAULT"` and `srcs: ["*.cpp", "impl/baz.cpp"]`.
`soong_config_module_type` modules will work best when used to wrap defaults
modules (`cc_defaults`, `java_defaults`, etc.), which can then be referenced
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index 80e4926..2d3ee39 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -33,6 +33,11 @@
const baseLibDep = "server_configurable_flags"
+const libBaseDep = "libbase"
+const libLogDep = "liblog"
+const libAconfigStorageReadApiCcDep = "libaconfig_storage_read_api_cc"
+const libAconfigStorageProtosCcDep = "libaconfig_storage_protos_cc"
+
type CcAconfigLibraryProperties struct {
// name of the aconfig_declarations module to generate a library for
Aconfig_declarations string
@@ -82,6 +87,11 @@
// Add a dependency for the aconfig flags base library if it is not forced read only
if mode != "force-read-only" {
deps.SharedLibs = append(deps.SharedLibs, baseLibDep)
+
+ deps.SharedLibs = append(deps.SharedLibs, libBaseDep)
+ deps.SharedLibs = append(deps.SharedLibs, libLogDep)
+ deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageReadApiCcDep)
+ deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageProtosCcDep)
}
// TODO: It'd be really nice if we could reexport this library and not make everyone do it.
diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go
index 05449bc..2e7fdc2 100644
--- a/aconfig/codegen/cc_aconfig_library_test.go
+++ b/aconfig/codegen/cc_aconfig_library_test.go
@@ -58,6 +58,26 @@
srcs: ["server_configurable_flags.cc"],
}
+ cc_library {
+ name: "libbase",
+ srcs: ["libbase.cc"],
+ }
+
+ cc_library {
+ name: "liblog",
+ srcs: ["liblog.cc"],
+ }
+
+ cc_library {
+ name: "libaconfig_storage_read_api_cc",
+ srcs: ["libaconfig_storage_read_api_cc.cc"],
+ }
+
+ cc_library {
+ name: "libaconfig_storage_protos_cc",
+ srcs: ["libaconfig_storage_protos_cc.cc"],
+ }
+
cc_aconfig_library {
name: "my_cc_aconfig_library",
aconfig_declarations: "my_aconfig_declarations",
@@ -100,6 +120,27 @@
srcs: ["server_configurable_flags.cc"],
}
+ cc_library {
+ name: "libbase",
+ srcs: ["libbase.cc"],
+ }
+
+ cc_library {
+ name: "liblog",
+ srcs: ["liblog.cc"],
+ }
+
+ cc_library {
+ name: "libaconfig_storage_read_api_cc",
+ srcs: ["libaconfig_storage_read_api_cc.cc"],
+ }
+
+ cc_library {
+ name: "libaconfig_storage_protos_cc",
+ srcs: ["libaconfig_storage_protos_cc.cc"],
+ }
+
+
cc_aconfig_library {
name: "my_cc_aconfig_library",
aconfig_declarations: "my_aconfig_declarations",
@@ -152,6 +193,30 @@
srcs: ["server_configurable_flags.cc"],
vendor_available: true,
}
+
+ cc_library {
+ name: "libbase",
+ srcs: ["libbase.cc"],
+ vendor_available: true,
+ }
+
+ cc_library {
+ name: "liblog",
+ srcs: ["liblog.cc"],
+ vendor_available: true,
+ }
+
+ cc_library {
+ name: "libaconfig_storage_read_api_cc",
+ srcs: ["libaconfig_storage_read_api_cc.cc"],
+ vendor_available: true,
+ }
+
+ cc_library {
+ name: "libaconfig_storage_protos_cc",
+ srcs: ["libaconfig_storage_protos_cc.cc"],
+ vendor_available: true,
+ }
`
result := android.GroupFixturePreparers(
PrepareForTestWithAconfigBuildComponents,
diff --git a/android/Android.bp b/android/Android.bp
index 4c59592..f130d3a 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -138,6 +138,7 @@
"selects_test.go",
"singleton_module_test.go",
"soong_config_modules_test.go",
+ "test_suites_test.go",
"util_test.go",
"variable_test.go",
"visibility_test.go",
diff --git a/android/arch.go b/android/arch.go
index 3224c3a..cd8882b 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -975,12 +975,18 @@
panic(fmt.Errorf("unexpected tag format %q", field.Tag))
}
// these tags don't need to be present in the runtime generated struct type.
- values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path", "replace_instead_of_append"})
+ // However replace_instead_of_append does, because it's read by the blueprint
+ // property extending util functions, which can operate on these generated arch
+ // property structs.
+ 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))
+ if values[0] != "replace_instead_of_append" || len(values) > 1 {
+ panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
+ }
+ field.Tag = `android:"replace_instead_of_append"`
+ } else {
+ field.Tag = ``
}
-
- field.Tag = ``
return true, field
}
return false, field
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index 90b49eb..38db929 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -64,6 +64,7 @@
// specified in `conditions_default` will only be used under the following conditions:
// bool variable: the variable is unspecified or not set to a true value
// value variable: the variable is unspecified
+// list variable: the variable is unspecified
// string variable: the variable is unspecified or the variable is set to a string unused in the
// given module. For example, string variable `test` takes values: "a" and "b",
// if the module contains a property `a` and `conditions_default`, when test=b,
@@ -104,6 +105,12 @@
// cflags: ["-DWIDTH=DEFAULT"],
// },
// },
+// impl: {
+// srcs: ["impl/%s"],
+// conditions_default: {
+// srcs: ["impl/default.cpp"],
+// },
+// },
// },
// }
//
@@ -122,6 +129,7 @@
// variables: ["board"],
// bool_variables: ["feature"],
// value_variables: ["width"],
+// list_variables: ["impl"],
// properties: ["cflags", "srcs"],
// }
//
@@ -135,8 +143,10 @@
// $(call add_soong_config_var_value, acme, board, soc_a)
// $(call add_soong_config_var_value, acme, feature, true)
// $(call add_soong_config_var_value, acme, width, 200)
+// $(call add_soong_config_var_value, acme, impl, foo.cpp bar.cpp)
//
-// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
+// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200" and srcs
+// ["*.cpp", "impl/foo.cpp", "impl/bar.cpp"].
//
// Alternatively, if acme BoardConfig.mk file contained:
//
@@ -148,7 +158,9 @@
// SOONG_CONFIG_acme_feature := false
//
// Then libacme_foo would build with cflags:
-// "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT".
+// "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT"
+// and with srcs:
+// ["*.cpp", "impl/default.cpp"].
//
// Similarly, if acme BoardConfig.mk file contained:
//
@@ -158,9 +170,13 @@
// feature \
//
// SOONG_CONFIG_acme_board := soc_c
+// SOONG_CONFIG_acme_impl := foo.cpp bar.cpp
//
// Then libacme_foo would build with cflags:
-// "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT".
+// "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT"
+// and with srcs:
+// ["*.cpp", "impl/foo.cpp", "impl/bar.cpp"].
+//
func SoongConfigModuleTypeImportFactory() Module {
module := &soongConfigModuleTypeImport{}
@@ -201,6 +217,7 @@
//
// bool variable: the variable is unspecified or not set to a true value
// value variable: the variable is unspecified
+// list variable: the variable is unspecified
// string variable: the variable is unspecified or the variable is set to a string unused in the
// given module. For example, string variable `test` takes values: "a" and "b",
// if the module contains a property `a` and `conditions_default`, when test=b,
@@ -209,56 +226,63 @@
//
// For example, an Android.bp file could have:
//
-// soong_config_module_type {
-// name: "acme_cc_defaults",
-// module_type: "cc_defaults",
-// config_namespace: "acme",
-// variables: ["board"],
-// bool_variables: ["feature"],
-// value_variables: ["width"],
-// properties: ["cflags", "srcs"],
-// }
+// soong_config_module_type {
+// name: "acme_cc_defaults",
+// module_type: "cc_defaults",
+// config_namespace: "acme",
+// variables: ["board"],
+// bool_variables: ["feature"],
+// value_variables: ["width"],
+// list_variables: ["impl"],
+// properties: ["cflags", "srcs"],
+// }
//
-// soong_config_string_variable {
-// name: "board",
-// values: ["soc_a", "soc_b"],
-// }
+// soong_config_string_variable {
+// name: "board",
+// values: ["soc_a", "soc_b"],
+// }
//
-// acme_cc_defaults {
-// name: "acme_defaults",
-// cflags: ["-DGENERIC"],
-// soong_config_variables: {
-// board: {
-// soc_a: {
-// cflags: ["-DSOC_A"],
-// },
-// soc_b: {
-// cflags: ["-DSOC_B"],
-// },
-// conditions_default: {
-// cflags: ["-DSOC_DEFAULT"],
-// },
+// acme_cc_defaults {
+// name: "acme_defaults",
+// cflags: ["-DGENERIC"],
+// soong_config_variables: {
+// board: {
+// soc_a: {
+// cflags: ["-DSOC_A"],
// },
-// feature: {
-// cflags: ["-DFEATURE"],
-// conditions_default: {
-// cflags: ["-DFEATURE_DEFAULT"],
-// },
+// soc_b: {
+// cflags: ["-DSOC_B"],
// },
-// width: {
-// cflags: ["-DWIDTH=%s"],
-// conditions_default: {
-// cflags: ["-DWIDTH=DEFAULT"],
-// },
+// conditions_default: {
+// cflags: ["-DSOC_DEFAULT"],
// },
// },
-// }
+// feature: {
+// cflags: ["-DFEATURE"],
+// conditions_default: {
+// cflags: ["-DFEATURE_DEFAULT"],
+// },
+// },
+// width: {
+// cflags: ["-DWIDTH=%s"],
+// conditions_default: {
+// cflags: ["-DWIDTH=DEFAULT"],
+// },
+// },
+// impl: {
+// srcs: ["impl/%s"],
+// conditions_default: {
+// srcs: ["impl/default.cpp"],
+// },
+// },
+// },
+// }
//
-// cc_library {
-// name: "libacme_foo",
-// defaults: ["acme_defaults"],
-// srcs: ["*.cpp"],
-// }
+// cc_library {
+// name: "libacme_foo",
+// defaults: ["acme_defaults"],
+// srcs: ["*.cpp"],
+// }
//
// If an acme BoardConfig.mk file contained:
//
@@ -270,8 +294,10 @@
// SOONG_CONFIG_acme_board := soc_a
// SOONG_CONFIG_acme_feature := true
// SOONG_CONFIG_acme_width := 200
+// SOONG_CONFIG_acme_impl := foo.cpp bar.cpp
//
-// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE".
+// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE" and srcs
+// ["*.cpp", "impl/foo.cpp", "impl/bar.cpp"].
func SoongConfigModuleTypeFactory() Module {
module := &soongConfigModuleTypeModule{}
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index c78b726..c910974 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -117,6 +117,10 @@
// inserted into the properties with %s substitution.
Value_variables []string
+ // the list of SOONG_CONFIG list variables that this module type will read. Each value will be
+ // inserted into the properties with %s substitution.
+ List_variables []string
+
// the list of properties that this module type will extend.
Properties []string
}
@@ -468,6 +472,18 @@
})
}
+ for _, name := range props.List_variables {
+ if err := checkVariableName(name); err != nil {
+ return nil, []error{fmt.Errorf("list_variables %s", err)}
+ }
+
+ mt.Variables = append(mt.Variables, &listVariable{
+ baseVariable: baseVariable{
+ variable: name,
+ },
+ })
+ }
+
return mt, nil
}
@@ -730,6 +746,90 @@
return nil
}
+// Struct to allow conditions set based on a list variable, supporting string substitution.
+type listVariable struct {
+ baseVariable
+}
+
+func (s *listVariable) variableValuesType() reflect.Type {
+ return emptyInterfaceType
+}
+
+// initializeProperties initializes a property to zero value of typ with an additional conditions
+// default field.
+func (s *listVariable) initializeProperties(v reflect.Value, typ reflect.Type) {
+ initializePropertiesWithDefault(v, typ)
+}
+
+// PropertiesToApply returns an interface{} value based on initializeProperties to be applied to
+// the module. If the variable was not set, conditions_default interface will be returned;
+// otherwise, the interface in values, without conditions_default will be returned with all
+// appropriate string substitutions based on variable being set.
+func (s *listVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
+ // If this variable was not referenced in the module, there are no properties to apply.
+ if !values.IsValid() || values.Elem().IsZero() {
+ return nil, nil
+ }
+ if !config.IsSet(s.variable) {
+ return conditionsDefaultField(values.Elem().Elem()).Interface(), nil
+ }
+ configValues := strings.Split(config.String(s.variable), " ")
+
+ values = removeDefault(values)
+ propStruct := values.Elem()
+ if !propStruct.IsValid() {
+ return nil, nil
+ }
+ if err := s.printfIntoPropertyRecursive(nil, propStruct, configValues); err != nil {
+ return nil, err
+ }
+
+ return values.Interface(), nil
+}
+
+func (s *listVariable) printfIntoPropertyRecursive(fieldName []string, propStruct reflect.Value, configValues []string) error {
+ for i := 0; i < propStruct.NumField(); i++ {
+ field := propStruct.Field(i)
+ kind := field.Kind()
+ if kind == reflect.Ptr {
+ if field.IsNil() {
+ continue
+ }
+ field = field.Elem()
+ kind = field.Kind()
+ }
+ switch kind {
+ case reflect.Slice:
+ elemType := field.Type().Elem()
+ newLen := field.Len() * len(configValues)
+ newField := reflect.MakeSlice(field.Type(), 0, newLen)
+ for j := 0; j < field.Len(); j++ {
+ for _, configValue := range configValues {
+ res := reflect.Indirect(reflect.New(elemType))
+ res.Set(field.Index(j))
+ err := printfIntoProperty(res, configValue)
+ if err != nil {
+ fieldName = append(fieldName, propStruct.Type().Field(i).Name)
+ return fmt.Errorf("soong_config_variables.%s.%s: %s", s.variable, strings.Join(fieldName, "."), err)
+ }
+ newField = reflect.Append(newField, res)
+ }
+ }
+ field.Set(newField)
+ case reflect.Struct:
+ fieldName = append(fieldName, propStruct.Type().Field(i).Name)
+ if err := s.printfIntoPropertyRecursive(fieldName, field, configValues); err != nil {
+ return err
+ }
+ fieldName = fieldName[:len(fieldName)-1]
+ default:
+ fieldName = append(fieldName, propStruct.Type().Field(i).Name)
+ return fmt.Errorf("soong_config_variables.%s.%s: unsupported property type %q", s.variable, strings.Join(fieldName, "."), kind)
+ }
+ }
+ return nil
+}
+
func printfIntoProperty(propertyValue reflect.Value, configValue string) error {
s := propertyValue.String()
@@ -739,7 +839,7 @@
}
if count > 1 {
- return fmt.Errorf("value variable properties only support a single '%%'")
+ return fmt.Errorf("list/value variable properties only support a single '%%'")
}
if !strings.Contains(s, "%s") {
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index 1da0b49..d76794c 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -291,11 +291,13 @@
type properties struct {
A *string
B bool
+ C []string
}
-type boolVarProps struct {
+type varProps struct {
A *string
B bool
+ C []string
Conditions_default *properties
}
@@ -311,6 +313,19 @@
My_value_var interface{}
}
+type listProperties struct {
+ C []string
+}
+
+type listVarProps struct {
+ C []string
+ Conditions_default *listProperties
+}
+
+type listSoongConfigVars struct {
+ List_var interface{}
+}
+
func Test_PropertiesToApply_Bool(t *testing.T) {
mt, _ := newModuleType(&ModuleTypeProperties{
Module_type: "foo",
@@ -330,7 +345,7 @@
Soong_config_variables boolSoongConfigVars
}{
Soong_config_variables: boolSoongConfigVars{
- Bool_var: &boolVarProps{
+ Bool_var: &varProps{
A: boolVarPositive.A,
B: boolVarPositive.B,
Conditions_default: conditionsDefault,
@@ -373,6 +388,59 @@
}
}
+func Test_PropertiesToApply_List(t *testing.T) {
+ mt, _ := newModuleType(&ModuleTypeProperties{
+ Module_type: "foo",
+ Config_namespace: "bar",
+ List_variables: []string{"my_list_var"},
+ Properties: []string{"c"},
+ })
+ conditionsDefault := &listProperties{
+ C: []string{"default"},
+ }
+ actualProps := &struct {
+ Soong_config_variables listSoongConfigVars
+ }{
+ Soong_config_variables: listSoongConfigVars{
+ List_var: &listVarProps{
+ C: []string{"A=%s", "B=%s"},
+ Conditions_default: conditionsDefault,
+ },
+ },
+ }
+ props := reflect.ValueOf(actualProps)
+
+ testCases := []struct {
+ name string
+ config SoongConfig
+ wantProps []interface{}
+ }{
+ {
+ name: "no_vendor_config",
+ config: Config(map[string]string{}),
+ wantProps: []interface{}{conditionsDefault},
+ },
+ {
+ name: "value_var_set",
+ config: Config(map[string]string{"my_list_var": "hello there"}),
+ wantProps: []interface{}{&listProperties{
+ C: []string{"A=hello", "A=there", "B=hello", "B=there"},
+ }},
+ },
+ }
+
+ for _, tc := range testCases {
+ gotProps, err := PropertiesToApply(mt, props, tc.config)
+ if err != nil {
+ t.Errorf("%s: Unexpected error in PropertiesToApply: %s", tc.name, err)
+ }
+
+ if !reflect.DeepEqual(gotProps, tc.wantProps) {
+ t.Errorf("%s: Expected %s, got %s", tc.name, tc.wantProps, gotProps)
+ }
+ }
+}
+
func Test_PropertiesToApply_Value(t *testing.T) {
mt, _ := newModuleType(&ModuleTypeProperties{
Module_type: "foo",
@@ -388,7 +456,7 @@
Soong_config_variables valueSoongConfigVars
}{
Soong_config_variables: valueSoongConfigVars{
- My_value_var: &boolVarProps{
+ My_value_var: &varProps{
A: proptools.StringPtr("A=%s"),
B: true,
Conditions_default: conditionsDefault,
@@ -524,7 +592,7 @@
Soong_config_variables stringSoongConfigVars
}{
Soong_config_variables: stringSoongConfigVars{
- String_var: &boolVarProps{
+ String_var: &varProps{
A: stringVarPositive.A,
B: stringVarPositive.B,
Conditions_default: conditionsDefault,
diff --git a/android/test_suites.go b/android/test_suites.go
index adcc15a..ff75f26 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -14,6 +14,11 @@
package android
+import (
+ "path/filepath"
+ "strings"
+)
+
func init() {
RegisterParallelSingletonType("testsuites", testSuiteFilesFactory)
}
@@ -23,8 +28,8 @@
}
type testSuiteFiles struct {
- robolectric WritablePath
- ravenwood WritablePath
+ robolectric []Path
+ ravenwood []Path
}
type TestSuiteModule interface {
@@ -48,53 +53,107 @@
})
t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"])
- ctx.Phony("robolectric-tests", t.robolectric)
+ ctx.Phony("robolectric-tests", t.robolectric...)
t.ravenwood = ravenwoodTestSuite(ctx, files["ravenwood-tests"])
- ctx.Phony("ravenwood-tests", t.ravenwood)
+ ctx.Phony("ravenwood-tests", t.ravenwood...)
}
func (t *testSuiteFiles) MakeVars(ctx MakeVarsContext) {
- ctx.DistForGoal("robolectric-tests", t.robolectric)
- ctx.DistForGoal("ravenwood-tests", t.ravenwood)
+ ctx.DistForGoal("robolectric-tests", t.robolectric...)
+ ctx.DistForGoal("ravenwood-tests", t.ravenwood...)
}
-func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath {
+func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path {
var installedPaths InstallPaths
for _, module := range SortedKeys(files) {
installedPaths = append(installedPaths, files[module]...)
}
- testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases")
- outputFile := PathForOutput(ctx, "packaging", "robolectric-tests.zip")
+ outputFile := pathForPackaging(ctx, "robolectric-tests.zip")
rule := NewRuleBuilder(pctx, ctx)
rule.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", outputFile).
FlagWithArg("-P ", "host/testcases").
- FlagWithArg("-C ", testCasesDir.String()).
+ FlagWithArg("-C ", pathForTestCases(ctx).String()).
FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()).
+ Flag("-sha256") // necessary to save cas_uploader's time
+
+ testList := buildTestList(ctx, "robolectric-tests_list", installedPaths)
+ testListZipOutputFile := pathForPackaging(ctx, "robolectric-tests_list.zip")
+
+ rule.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", testListZipOutputFile).
+ FlagWithArg("-C ", pathForPackaging(ctx).String()).
+ FlagWithInput("-f ", testList).
Flag("-sha256")
+
rule.Build("robolectric_tests_zip", "robolectric-tests.zip")
- return outputFile
+ return []Path{outputFile, testListZipOutputFile}
}
-func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath {
+func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path {
var installedPaths InstallPaths
for _, module := range SortedKeys(files) {
installedPaths = append(installedPaths, files[module]...)
}
- testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases")
- outputFile := PathForOutput(ctx, "packaging", "ravenwood-tests.zip")
+ outputFile := pathForPackaging(ctx, "ravenwood-tests.zip")
rule := NewRuleBuilder(pctx, ctx)
rule.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", outputFile).
FlagWithArg("-P ", "host/testcases").
- FlagWithArg("-C ", testCasesDir.String()).
+ FlagWithArg("-C ", pathForTestCases(ctx).String()).
FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()).
+ Flag("-sha256") // necessary to save cas_uploader's time
+
+ testList := buildTestList(ctx, "ravenwood-tests_list", installedPaths)
+ testListZipOutputFile := pathForPackaging(ctx, "ravenwood-tests_list.zip")
+
+ rule.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", testListZipOutputFile).
+ FlagWithArg("-C ", pathForPackaging(ctx).String()).
+ FlagWithInput("-f ", testList).
Flag("-sha256")
+
rule.Build("ravenwood_tests_zip", "ravenwood-tests.zip")
+ return []Path{outputFile, testListZipOutputFile}
+}
+
+func buildTestList(ctx SingletonContext, listFile string, installedPaths InstallPaths) Path {
+ buf := &strings.Builder{}
+ for _, p := range installedPaths {
+ if p.Ext() != ".config" {
+ continue
+ }
+ pc, err := toTestListPath(p.String(), pathForTestCases(ctx).String(), "host/testcases")
+ if err != nil {
+ ctx.Errorf("Failed to convert path: %s, %v", p.String(), err)
+ continue
+ }
+ buf.WriteString(pc)
+ buf.WriteString("\n")
+ }
+ outputFile := pathForPackaging(ctx, listFile)
+ WriteFileRuleVerbatim(ctx, outputFile, buf.String())
return outputFile
}
+
+func toTestListPath(path, relativeRoot, prefix string) (string, error) {
+ dest, err := filepath.Rel(relativeRoot, path)
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(prefix, dest), nil
+}
+
+func pathForPackaging(ctx PathContext, pathComponents ...string) OutputPath {
+ pathComponents = append([]string{"packaging"}, pathComponents...)
+ return PathForOutput(ctx, pathComponents...)
+}
+
+func pathForTestCases(ctx PathContext) InstallPath {
+ return pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases")
+}
diff --git a/android/test_suites_test.go b/android/test_suites_test.go
new file mode 100644
index 0000000..db9a34d
--- /dev/null
+++ b/android/test_suites_test.go
@@ -0,0 +1,117 @@
+// Copyright 2024 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 (
+ "path/filepath"
+ "testing"
+)
+
+func TestBuildTestList(t *testing.T) {
+ t.Parallel()
+ ctx := GroupFixturePreparers(
+ prepareForFakeTestSuite,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterParallelSingletonType("testsuites", testSuiteFilesFactory)
+ }),
+ ).RunTestWithBp(t, `
+ fake_module {
+ name: "module1",
+ outputs: [
+ "Test1/Test1.config",
+ "Test1/Test1.apk",
+ ],
+ test_suites: ["ravenwood-tests"],
+ }
+ fake_module {
+ name: "module2",
+ outputs: [
+ "Test2/Test21/Test21.config",
+ "Test2/Test21/Test21.apk",
+ ],
+ test_suites: ["ravenwood-tests", "robolectric-tests"],
+ }
+ fake_module {
+ name: "module_without_config",
+ outputs: [
+ "BadTest/BadTest.jar",
+ ],
+ test_suites: ["robolectric-tests"],
+ }
+ `)
+
+ config := ctx.SingletonForTests("testsuites")
+ allOutputs := config.AllOutputs()
+
+ wantContents := map[string]string{
+ "robolectric-tests.zip": "",
+ "robolectric-tests_list.zip": "",
+ "robolectric-tests_list": `host/testcases/Test2/Test21/Test21.config
+`,
+ "ravenwood-tests.zip": "",
+ "ravenwood-tests_list.zip": "",
+ "ravenwood-tests_list": `host/testcases/Test1/Test1.config
+host/testcases/Test2/Test21/Test21.config
+`,
+ }
+ for _, output := range allOutputs {
+ want, ok := wantContents[filepath.Base(output)]
+ if !ok {
+ t.Errorf("unexpected output: %q", output)
+ continue
+ }
+
+ got := ""
+ if want != "" {
+ got = ContentFromFileRuleForTests(t, ctx.TestContext, config.MaybeOutput(output))
+ }
+
+ if want != got {
+ t.Errorf("want %q, got %q", want, got)
+ }
+ }
+}
+
+type fake_module struct {
+ ModuleBase
+ props struct {
+ Outputs []string
+ Test_suites []string
+ }
+}
+
+func fakeTestSuiteFactory() Module {
+ module := &fake_module{}
+ base := module.base()
+ module.AddProperties(&base.nameProperties, &module.props)
+ InitAndroidModule(module)
+ return module
+}
+
+var prepareForFakeTestSuite = GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake_module", fakeTestSuiteFactory)
+ }),
+)
+
+func (f *fake_module) GenerateAndroidBuildActions(ctx ModuleContext) {
+ for _, output := range f.props.Outputs {
+ ctx.InstallFile(pathForTestCases(ctx), output, nil)
+ }
+}
+
+func (f *fake_module) TestSuites() []string {
+ return f.props.Test_suites
+}
diff --git a/apex/aconfig_test.go b/apex/aconfig_test.go
index 3e44f0b..3de9286 100644
--- a/apex/aconfig_test.go
+++ b/apex/aconfig_test.go
@@ -162,6 +162,18 @@
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
+ cc_library {
+ name: "libbase",
+ srcs: ["libbase.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_read_api_cc",
+ srcs: ["libaconfig_storage_read_api_cc.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_protos_cc",
+ srcs: ["libaconfig_storage_protos_cc.cc"],
+ }
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
@@ -410,6 +422,18 @@
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
+ cc_library {
+ name: "libbase",
+ srcs: ["libbase.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_read_api_cc",
+ srcs: ["libaconfig_storage_read_api_cc.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_protos_cc",
+ srcs: ["libaconfig_storage_protos_cc.cc"],
+ }
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
@@ -460,6 +484,18 @@
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
+ cc_library {
+ name: "libbase",
+ srcs: ["libbase.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_read_api_cc",
+ srcs: ["libaconfig_storage_read_api_cc.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_protos_cc",
+ srcs: ["libaconfig_storage_protos_cc.cc"],
+ }
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2441b02..8a3735c 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -10691,6 +10691,18 @@
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
+ cc_library {
+ name: "libbase",
+ srcs: ["libbase.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_read_api_cc",
+ srcs: ["libaconfig_storage_read_api_cc.cc"],
+ }
+ cc_library {
+ name: "libaconfig_storage_protos_cc",
+ srcs: ["libaconfig_storage_protos_cc.cc"],
+ }
`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
diff --git a/cc/Android.bp b/cc/Android.bp
index 5ba9427..9ce8933 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -96,7 +96,6 @@
"gen_test.go",
"genrule_test.go",
"library_headers_test.go",
- "library_stub_test.go",
"library_test.go",
"lto_test.go",
"ndk_test.go",
diff --git a/cc/config/global.go b/cc/config/global.go
index ffd6d7e..16b5e09 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -295,9 +295,6 @@
// New warnings to be fixed after clang-r475365
"-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
"-Wno-error=enum-constexpr-conversion", // http://b/243964282
- // New warnings to be fixed after clang-r522817
- "-Wno-error=invalid-offsetof",
- "-Wno-error=thread-safety-reference-return",
// Irrelevant on Android because _we_ don't use exceptions, but causes
// lots of build noise because libcxx/libcxxabi do. This can probably
@@ -305,9 +302,6 @@
// until then because it causes warnings in the _callers_, not the
// project itself.
"-Wno-deprecated-dynamic-exception-spec",
-
- // Allow using VLA CXX extension.
- "-Wno-vla-cxx-extension",
}
noOverride64GlobalCflags = []string{}
@@ -392,7 +386,7 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r522817"
+ ClangDefaultVersion = "clang-r510928"
ClangDefaultShortVersion = "18"
// Directories with warnings from Android.bp files.
diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go
deleted file mode 100644
index 4df0a41..0000000
--- a/cc/library_stub_test.go
+++ /dev/null
@@ -1,459 +0,0 @@
-// Copyright 2021 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 cc
-
-import (
- _ "fmt"
- _ "sort"
-
- "testing"
-
- "android/soong/android"
-
- "github.com/google/blueprint"
-)
-
-func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool {
- t.Helper()
- var found bool
- ctx.VisitDirectDeps(from, func(dep blueprint.Module) {
- if dep == to {
- found = true
- }
- })
- return found
-}
-
-func TestApiLibraryReplacesExistingModule(t *testing.T) {
- bp := `
- cc_library {
- name: "libfoo",
- shared_libs: ["libbar"],
- vendor_available: true,
- }
-
- cc_library {
- name: "libbar",
- }
-
- cc_api_library {
- name: "libbar",
- vendor_available: true,
- src: "libbar.so",
- }
-
- api_imports {
- name: "api_imports",
- shared_libs: [
- "libbar",
- ],
- }
- `
-
- ctx := prepareForCcTest.RunTestWithBp(t, bp)
-
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
- libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
- libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
-
- android.AssertBoolEquals(t, "original library should be linked with non-stub variant", true, hasDirectDependency(t, ctx, libfoo, libbar))
- android.AssertBoolEquals(t, "Stub library from API surface should be not linked with non-stub variant", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
-
- libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
- libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
-
- android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfooVendor, libbar))
- android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfooVendor, libbarApiImportVendor))
-}
-
-func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
- bp := `
- cc_library {
- name: "libfoo",
- shared_libs: ["libbar"],
- vendor: true,
- }
-
- cc_api_library {
- name: "libbar",
- src: "libbar.so",
- vendor_available: true,
- }
-
- api_imports {
- name: "api_imports",
- shared_libs: [
- "libbar",
- ],
- }
- `
-
- ctx := prepareForCcTest.RunTestWithBp(t, bp)
-
- libfoo := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
- libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
-
- android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
-}
-
-func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) {
- bp := `
- cc_library {
- name: "libfoo",
- shared_libs: ["libbar"],
- vendor_available: true,
- }
-
- cc_library {
- name: "libbar",
- vendor_available: true,
- }
-
- cc_api_library {
- name: "libbar",
- src: "libbar.so",
- vendor_available: true,
- }
-
- api_imports {
- name: "api_imports",
- shared_libs: [],
- }
- `
-
- ctx := prepareForCcTest.RunTestWithBp(t, bp)
-
- libfoo := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
- libbar := ctx.ModuleForTests("libbar", "android_vendor_arm64_armv8-a_shared").Module()
- libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
-
- android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
- android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
-}
-
-func TestExportDirFromStubLibrary(t *testing.T) {
- bp := `
- cc_library {
- name: "libfoo",
- export_include_dirs: ["source_include_dir"],
- export_system_include_dirs: ["source_system_include_dir"],
- vendor_available: true,
- }
- cc_api_library {
- name: "libfoo",
- export_include_dirs: ["stub_include_dir"],
- export_system_include_dirs: ["stub_system_include_dir"],
- vendor_available: true,
- src: "libfoo.so",
- }
- api_imports {
- name: "api_imports",
- shared_libs: [
- "libfoo",
- ],
- header_libs: [],
- }
- // vendor binary
- cc_binary {
- name: "vendorbin",
- vendor: true,
- srcs: ["vendor.cc"],
- shared_libs: ["libfoo"],
- }
- `
- ctx := prepareForCcTest.RunTestWithBp(t, bp)
- vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"]
- android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir")
- android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir")
- android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir")
- android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir")
-
- vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
- // Building the stub.so file first assembles its .h files in multi-tree out.
- // These header files are required for compiling the other API domain (vendor in this case)
- android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
-}
-
-func TestApiLibraryWithLlndkVariant(t *testing.T) {
- bp := `
- cc_binary {
- name: "binfoo",
- vendor: true,
- srcs: ["binfoo.cc"],
- shared_libs: ["libbar"],
- }
-
- cc_api_library {
- name: "libbar",
- // TODO(b/244244438) Remove src property once all variants are implemented.
- src: "libbar.so",
- vendor_available: true,
- variants: [
- "llndk",
- ],
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "llndk",
- src: "libbar_llndk.so",
- export_include_dirs: ["libbar_llndk_include"]
- }
-
- api_imports {
- name: "api_imports",
- shared_libs: [
- "libbar",
- ],
- header_libs: [],
- }
- `
-
- ctx := prepareForCcTest.RunTestWithBp(t, bp)
-
- binfoo := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Module()
- libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
- libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor_arm64_armv8-a").Module()
-
- android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport))
- android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
-
- binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Rule("ld").Args["libFlags"]
- android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar.llndk.apiimport.so")
-
- binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"]
- android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include")
-}
-
-func TestApiLibraryWithNdkVariant(t *testing.T) {
- bp := `
- cc_binary {
- name: "binfoo",
- sdk_version: "29",
- srcs: ["binfoo.cc"],
- shared_libs: ["libbar"],
- stl: "c++_shared",
- }
-
- cc_binary {
- name: "binbaz",
- sdk_version: "30",
- srcs: ["binbaz.cc"],
- shared_libs: ["libbar"],
- stl: "c++_shared",
- }
-
- cc_binary {
- name: "binqux",
- srcs: ["binfoo.cc"],
- shared_libs: ["libbar"],
- }
-
- cc_library {
- name: "libbar",
- srcs: ["libbar.cc"],
- }
-
- cc_api_library {
- name: "libbar",
- // TODO(b/244244438) Remove src property once all variants are implemented.
- src: "libbar.so",
- variants: [
- "ndk.29",
- "ndk.30",
- "ndk.current",
- ],
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "ndk",
- version: "29",
- src: "libbar_ndk_29.so",
- export_include_dirs: ["libbar_ndk_29_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "ndk",
- version: "30",
- src: "libbar_ndk_30.so",
- export_include_dirs: ["libbar_ndk_30_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "ndk",
- version: "current",
- src: "libbar_ndk_current.so",
- export_include_dirs: ["libbar_ndk_current_include"]
- }
-
- api_imports {
- name: "api_imports",
- shared_libs: [
- "libbar",
- ],
- header_libs: [],
- }
- `
-
- ctx := prepareForCcTest.RunTestWithBp(t, bp)
-
- binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
- libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
- libbarApiVariantv29 := ctx.ModuleForTests("libbar.ndk.29.apiimport", "android_arm64_armv8-a_sdk").Module()
- libbarApiImportv30 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_30").Module()
- libbarApiVariantv30 := ctx.ModuleForTests("libbar.ndk.30.apiimport", "android_arm64_armv8-a_sdk").Module()
-
- android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
- android.AssertBoolEquals(t, "Stub library variant from API surface should be linked with target version", true, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv29))
- android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportv30))
- android.AssertBoolEquals(t, "Stub library variant from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv30))
-
- binbaz := ctx.ModuleForTests("binbaz", "android_arm64_armv8-a_sdk").Module()
-
- android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportv30))
- android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
-
- binFooLibFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("ld").Args["libFlags"]
- android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar.ndk.29.apiimport.so")
-
- binFooCFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("cc").Args["cFlags"]
- android.AssertStringDoesContain(t, "Binary using sdk should include headers from the NDK variant source", binFooCFlags, "-Ilibbar_ndk_29_include")
-
- binQux := ctx.ModuleForTests("binqux", "android_arm64_armv8-a").Module()
- android.AssertBoolEquals(t, "NDK Stub library from API surface should not be linked with nonSdk binary", false,
- (hasDirectDependency(t, ctx, binQux, libbarApiImportv30) || hasDirectDependency(t, ctx, binQux, libbarApiImportv29)))
-}
-
-func TestApiLibraryWithMultipleVariants(t *testing.T) {
- bp := `
- cc_binary {
- name: "binfoo",
- sdk_version: "29",
- srcs: ["binfoo.cc"],
- shared_libs: ["libbar"],
- stl: "c++_shared",
- }
-
- cc_binary {
- name: "binbaz",
- vendor: true,
- srcs: ["binbaz.cc"],
- shared_libs: ["libbar"],
- }
-
- cc_library {
- name: "libbar",
- srcs: ["libbar.cc"],
- }
-
- cc_api_library {
- name: "libbar",
- // TODO(b/244244438) Remove src property once all variants are implemented.
- src: "libbar.so",
- vendor_available: true,
- variants: [
- "llndk",
- "ndk.29",
- "ndk.30",
- "ndk.current",
- "apex.29",
- "apex.30",
- "apex.current",
- ],
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "ndk",
- version: "29",
- src: "libbar_ndk_29.so",
- export_include_dirs: ["libbar_ndk_29_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "ndk",
- version: "30",
- src: "libbar_ndk_30.so",
- export_include_dirs: ["libbar_ndk_30_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "ndk",
- version: "current",
- src: "libbar_ndk_current.so",
- export_include_dirs: ["libbar_ndk_current_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "apex",
- version: "29",
- src: "libbar_apex_29.so",
- export_include_dirs: ["libbar_apex_29_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "apex",
- version: "30",
- src: "libbar_apex_30.so",
- export_include_dirs: ["libbar_apex_30_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "apex",
- version: "current",
- src: "libbar_apex_current.so",
- export_include_dirs: ["libbar_apex_current_include"]
- }
-
- cc_api_variant {
- name: "libbar",
- variant: "llndk",
- src: "libbar_llndk.so",
- export_include_dirs: ["libbar_llndk_include"]
- }
-
- api_imports {
- name: "api_imports",
- shared_libs: [
- "libbar",
- ],
- apex_shared_libs: [
- "libbar",
- ],
- }
- `
- ctx := prepareForCcTest.RunTestWithBp(t, bp)
-
- binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
- libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
- libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
-
- android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
- android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk))
-
- binbaz := ctx.ModuleForTests("binbaz", "android_vendor_arm64_armv8-a").Module()
-
- android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk))
- android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
-
-}
diff --git a/cc/sdk.go b/cc/sdk.go
index 736a958..ce0fdc2 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -59,35 +59,6 @@
modules[1].(*Module).Properties.PreventInstall = true
}
ctx.AliasVariation("")
- } else if isCcModule && ccModule.isImportedApiLibrary() {
- apiLibrary, _ := ccModule.linker.(*apiLibraryDecorator)
- if apiLibrary.hasNDKStubs() && ccModule.canUseSdk() {
- variations := []string{"sdk"}
- if apiLibrary.hasApexStubs() {
- variations = append(variations, "")
- }
- // Handle cc_api_library module with NDK stubs and variants only which can use SDK
- modules := ctx.CreateVariations(variations...)
- // Mark the SDK variant.
- modules[0].(*Module).Properties.IsSdkVariant = true
- if ctx.Config().UnbundledBuildApps() {
- if apiLibrary.hasApexStubs() {
- // For an unbundled apps build, hide the platform variant from Make.
- modules[1].(*Module).Properties.HideFromMake = true
- }
- modules[1].(*Module).Properties.PreventInstall = true
- } else {
- // For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when
- // exposed to Make.
- modules[0].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
- // SDK variant is not supposed to be installed
- modules[0].(*Module).Properties.PreventInstall = true
- }
- } else {
- ccModule.Properties.Sdk_version = nil
- ctx.CreateVariations("")
- ctx.AliasVariation("")
- }
} else {
if isCcModule {
// Clear the sdk_version property for modules that don't have an SDK variant so
diff --git a/cmd/release_config/crunch_flags/main.go b/cmd/release_config/crunch_flags/main.go
index 616674b..69abba2 100644
--- a/cmd/release_config/crunch_flags/main.go
+++ b/cmd/release_config/crunch_flags/main.go
@@ -89,7 +89,10 @@
for _, line := range lines {
if comment := commentRegexp.FindStringSubmatch(commentRegexp.FindString(line)); comment != nil {
// Description is the text from any contiguous series of lines before a `flag()` call.
- description += fmt.Sprintf(" %s", strings.TrimSpace(comment[commentRegexp.SubexpIndex("comment")]))
+ descLine := strings.TrimSpace(comment[commentRegexp.SubexpIndex("comment")])
+ if !strings.HasPrefix(descLine, "keep-sorted") {
+ description += fmt.Sprintf(" %s", descLine)
+ }
continue
}
matches := declRegexp.FindStringSubmatch(declRegexp.FindString(line))
@@ -218,7 +221,7 @@
} else {
fmt.Printf("Processing %s\n", path)
}
- configRegexp, err := regexp.Compile("^..call[[:space:]]+declare-release-config,[[:space:]]+(?<name>[_a-z0-0A-Z]+),[[:space:]]+(?<files>[^,]*)(,[[:space:]]*(?<inherits>.*)|[[:space:]]*)[)]$")
+ configRegexp, err := regexp.Compile("^..call[[:space:]]+declare-release-config,[[:space:]]+(?<name>[_a-z0-9A-Z]+),[[:space:]]+(?<files>[^,]*)(,[[:space:]]*(?<inherits>.*)|[[:space:]]*)[)]$")
if err != nil {
return err
}
diff --git a/java/aar.go b/java/aar.go
index f8955ce..0a91ff4 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -418,6 +418,9 @@
if a.isLibrary {
linkFlags = append(linkFlags, "--static-lib")
}
+ if opts.forceNonFinalResourceIDs {
+ linkFlags = append(linkFlags, "--non-final-ids")
+ }
linkFlags = append(linkFlags, "--no-static-lib-packages")
if a.isLibrary && a.useResourceProcessorBusyBox(ctx) {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 870c643..ffd3caf 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -708,8 +708,8 @@
return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
}
-func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
- srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
+func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
+ srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
@@ -739,14 +739,14 @@
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
Flag(config.MetalavaAddOpens).
- FlagWithArg("--java-source ", javaVersion.String()).
- FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
+ FlagWithArg("--java-source ", params.javaVersion.String()).
+ FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
FlagWithInput("@", srcJarList)
// Metalava does not differentiate between bootclasspath and classpath and has not done so for
// years, so it is unlikely to change any time soon.
- combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
- combinedPaths = append(combinedPaths, classpath.Paths()...)
+ combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
+ combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
if len(combinedPaths) > 0 {
cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
}
@@ -827,8 +827,7 @@
srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
- cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
- params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
+ cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig)
cmd.Implicits(d.Javadoc.implicits)
d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
@@ -954,11 +953,8 @@
if d.properties.Check_api.Api_lint.New_since != nil {
newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
}
- if len(newSince) > 0 {
- cmd.FlagForEachInput("--api-lint ", newSince)
- } else {
- cmd.Flag("--api-lint")
- }
+ cmd.Flag("--api-lint")
+ cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
diff --git a/java/robolectric.go b/java/robolectric.go
index 9e8850c..18386c9 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -46,6 +46,7 @@
var (
roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
roboRuntimesTag = dependencyTag{name: "roboRuntimes"}
+ roboRuntimeOnlyTag = dependencyTag{name: "roboRuntimeOnlyTag"}
)
type robolectricProperties struct {
@@ -70,6 +71,9 @@
// Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectric
// to use. /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows
Upstream *bool
+
+ // Use strict mode to limit access of Robolectric API directly. See go/roboStrictMode
+ Strict_mode *bool
}
type robolectricTest struct {
@@ -112,7 +116,7 @@
if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
- } else {
+ } else if !proptools.Bool(r.robolectricProperties.Strict_mode) {
if proptools.Bool(r.robolectricProperties.Upstream) {
ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib+"_upstream")
} else {
@@ -120,6 +124,10 @@
}
}
+ if proptools.Bool(r.robolectricProperties.Strict_mode) {
+ ctx.AddVariationDependencies(nil, roboRuntimeOnlyTag, robolectricCurrentLib+"_upstream")
+ }
+
ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
@@ -192,19 +200,25 @@
combinedJarJars = append(combinedJarJars, instrumentedApp.implementationAndResourcesJar)
}
- handleLibDeps := func(dep android.Module) {
+ handleLibDeps := func(dep android.Module, runtimeOnly bool) {
m, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
- r.libs = append(r.libs, ctx.OtherModuleName(dep))
+ if !runtimeOnly {
+ r.libs = append(r.libs, ctx.OtherModuleName(dep))
+ }
if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
combinedJarJars = append(combinedJarJars, m.ImplementationAndResourcesJars...)
}
}
for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
- handleLibDeps(dep)
+ handleLibDeps(dep, false)
}
for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) {
- handleLibDeps(dep)
+ handleLibDeps(dep, false)
+ }
+ // handle the runtimeOnly tag for strict_mode
+ for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyTag) {
+ handleLibDeps(dep, true)
}
r.combinedJar = android.PathForModuleOut(ctx, "robolectric_combined", r.outputFile.Base())
diff --git a/java/sdk_library.go b/java/sdk_library.go
index bb5730d..113071f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -3316,6 +3316,7 @@
android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
+ ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
}
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 11ba74d..eaed1b9 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -101,6 +101,9 @@
//
// "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]"
Custom_bindgen string
+
+ // flag to indicate if bindgen should handle `static inline` functions (default is false)
+ Handle_static_inline bool
}
type bindgenDecorator struct {
@@ -232,6 +235,9 @@
bindgenFlags := defaultBindgenFlags
bindgenFlags = append(bindgenFlags, esc(b.Properties.Bindgen_flags)...)
+ if b.Properties.Handle_static_inline {
+ bindgenFlags = append(bindgenFlags, "--experimental --wrap-static-fns")
+ }
// cat reads from stdin if its command line is empty,
// so we pass in /dev/null if there are no other flag files
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index 0c0a6da..11cfe4e 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -227,3 +227,22 @@
// TODO: The best we can do right now is check $flagfiles. Once bindgen.go switches to RuleBuilder,
// we may be able to check libbinder.RuleParams.Command to see if it contains $(cat /dev/null flag_file.txt)
}
+
+
+func TestBindgenHandleStaticInlining(t *testing.T) {
+ ctx := testRust(t, `
+ rust_bindgen {
+ name: "libbindgen",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
+ handle_static_inline: true
+ }
+ `)
+ libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+ // Make sure the flag to support `static inline` functions is present
+ if !strings.Contains(libbindgen.Args["flags"], "--wrap-static-fns") {
+ t.Errorf("missing flag to handle static inlining in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
+ }
+}