Merge "Create a framework.aidl for non-updatable platform" into rvc-dev
diff --git a/README.md b/README.md
index 3eac87b..8b028a8 100644
--- a/README.md
+++ b/README.md
@@ -421,6 +421,7 @@
config_namespace: "acme",
variables: ["board"],
bool_variables: ["feature"],
+ value_variables: ["width"],
properties: ["cflags", "srcs"],
}
@@ -431,8 +432,9 @@
```
This example describes a new `acme_cc_defaults` module type that extends the
-`cc_defaults` module type, with two additional conditionals based on variables
-`board` and `feature`, which can affect properties `cflags` and `srcs`.
+`cc_defaults` module type, with three additional conditionals based on
+variables `board`, `feature` and `width`, which can affect properties `cflags`
+and `srcs`.
The values of the variables can be set from a product's `BoardConfig.mk` file:
```
@@ -443,6 +445,7 @@
SOONG_CONFIG_acme_board := soc_a
SOONG_CONFIG_acme_feature := true
+SOONG_CONFIG_acme_width := 200
```
The `acme_cc_defaults` module type can be used anywhere after the definition in
@@ -471,6 +474,9 @@
feature: {
cflags: ["-DFEATURE"],
},
+ width: {
+ cflags: ["-DWIDTH=%s"],
+ },
},
}
@@ -482,7 +488,7 @@
```
With the `BoardConfig.mk` snippet above, libacme_foo would build with
-cflags "-DGENERIC -DSOC_A -DFEATURE".
+cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
`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/android/config.go b/android/config.go
index 5e09214..a0418d8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -570,8 +570,8 @@
return String(c.productVariables.BuildId)
}
-func (c *config) BuildNumberFromFile() string {
- return String(c.productVariables.BuildNumberFromFile)
+func (c *config) BuildNumberFile(ctx PathContext) Path {
+ return PathForOutput(ctx, String(c.productVariables.BuildNumberFile))
}
// DeviceName returns the name of the current device target
diff --git a/android/neverallow.go b/android/neverallow.go
index 8fcfb8a..ea307ca 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -17,6 +17,7 @@
import (
"path/filepath"
"reflect"
+ "regexp"
"strconv"
"strings"
@@ -146,7 +147,8 @@
rules := []Rule{
NeverAllow().
NotIn(coreLibraryProjects...).
- With("sdk_version", "none"),
+ With("sdk_version", "none").
+ WithoutMatcher("name", Regexp("^android_.*stubs_current$")),
}
return rules
@@ -254,6 +256,18 @@
return ".starts-with(" + m.prefix + ")"
}
+type regexMatcher struct {
+ re *regexp.Regexp
+}
+
+func (m *regexMatcher) test(value string) bool {
+ return m.re.MatchString(value)
+}
+
+func (m *regexMatcher) String() string {
+ return ".regexp(" + m.re.String() + ")"
+}
+
type ruleProperty struct {
fields []string // e.x.: Vndk.Enabled
matcher ValueMatcher
@@ -457,6 +471,14 @@
return &startsWithMatcher{prefix}
}
+func Regexp(re string) ValueMatcher {
+ r, err := regexp.Compile(re)
+ if err != nil {
+ panic(err)
+ }
+ return ®exMatcher{r}
+}
+
// assorted utils
func cleanPaths(paths []string) []string {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 6f07a4a..7992936 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -227,6 +227,16 @@
},
},
{
+ name: "sdk_version: \"none\" on android_*stubs_current stub",
+ fs: map[string][]byte{
+ "frameworks/base/Android.bp": []byte(`
+ java_library {
+ name: "android_stubs_current",
+ sdk_version: "none",
+ }`),
+ },
+ },
+ {
name: "sdk_version: \"none\" outside core libraries",
fs: map[string][]byte{
"Android.bp": []byte(`
diff --git a/android/rule_builder.go b/android/rule_builder.go
index b4f144a..9005f07 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -162,9 +162,10 @@
r.Command().Text("rm").Flag("-f").Outputs(temporariesList)
}
-// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take input paths, such
-// as RuleBuilderCommand.Input, RuleBuilderComand.Implicit, or RuleBuilderCommand.FlagWithInput. Inputs to a command
-// that are also outputs of another command in the same RuleBuilder are filtered out.
+// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take
+// input paths, such as RuleBuilderCommand.Input, RuleBuilderComand.Implicit, or
+// RuleBuilderCommand.FlagWithInput. Inputs to a command that are also outputs of another command
+// in the same RuleBuilder are filtered out. The list is sorted and duplicates removed.
func (r *RuleBuilder) Inputs() Paths {
outputs := r.outputSet()
depFiles := r.depFileSet()
@@ -193,6 +194,28 @@
return inputList
}
+// OrderOnlys returns the list of paths that were passed to the RuleBuilderCommand.OrderOnly or
+// RuleBuilderCommand.OrderOnlys. The list is sorted and duplicates removed.
+func (r *RuleBuilder) OrderOnlys() Paths {
+ orderOnlys := make(map[string]Path)
+ for _, c := range r.commands {
+ for _, orderOnly := range c.orderOnlys {
+ orderOnlys[orderOnly.String()] = orderOnly
+ }
+ }
+
+ var orderOnlyList Paths
+ for _, orderOnly := range orderOnlys {
+ orderOnlyList = append(orderOnlyList, orderOnly)
+ }
+
+ sort.Slice(orderOnlyList, func(i, j int) bool {
+ return orderOnlyList[i].String() < orderOnlyList[j].String()
+ })
+
+ return orderOnlyList
+}
+
func (r *RuleBuilder) outputSet() map[string]WritablePath {
outputs := make(map[string]WritablePath)
for _, c := range r.commands {
@@ -203,8 +226,9 @@
return outputs
}
-// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take output paths, such
-// as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or RuleBuilderCommand.FlagWithInput.
+// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take
+// output paths, such as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or
+// RuleBuilderCommand.FlagWithInput. The list is sorted and duplicates removed.
func (r *RuleBuilder) Outputs() WritablePaths {
outputs := r.outputSet()
@@ -262,7 +286,8 @@
return tools
}
-// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method.
+// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method. The
+// list is sorted and duplicates removed.
func (r *RuleBuilder) Tools() Paths {
toolsSet := r.toolsSet()
@@ -337,6 +362,7 @@
ctx.Build(pctx, BuildParams{
Rule: ErrorRule,
Outputs: r.Outputs(),
+ OrderOnly: r.OrderOnlys(),
Description: desc,
Args: map[string]string{
"error": "missing dependencies: " + strings.Join(r.missingDeps, ", "),
@@ -453,6 +479,7 @@
type RuleBuilderCommand struct {
buf strings.Builder
inputs Paths
+ orderOnlys Paths
outputs WritablePaths
depFiles WritablePaths
tools Paths
@@ -475,6 +502,10 @@
return path.String()
}
+func (c *RuleBuilderCommand) addOrderOnly(path Path) {
+ c.orderOnlys = append(c.orderOnlys, path)
+}
+
func (c *RuleBuilderCommand) outputStr(path Path) string {
if c.sbox {
// Errors will be handled in RuleBuilder.Build where we have a context to report them
@@ -604,6 +635,22 @@
return c
}
+// OrderOnly adds the specified input path to the dependencies returned by RuleBuilder.OrderOnlys
+// without modifying the command line.
+func (c *RuleBuilderCommand) OrderOnly(path Path) *RuleBuilderCommand {
+ c.addOrderOnly(path)
+ return c
+}
+
+// OrderOnlys adds the specified input paths to the dependencies returned by RuleBuilder.OrderOnlys
+// without modifying the command line.
+func (c *RuleBuilderCommand) OrderOnlys(paths Paths) *RuleBuilderCommand {
+ for _, path := range paths {
+ c.addOrderOnly(path)
+ }
+ return c
+}
+
// Output adds the specified output path to the command line. The path will also be added to the outputs returned by
// RuleBuilder.Outputs.
func (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand {
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index acf8127..c41b067 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -265,14 +265,16 @@
func TestRuleBuilder(t *testing.T) {
fs := map[string][]byte{
- "dep_fixer": nil,
- "input": nil,
- "Implicit": nil,
- "Input": nil,
- "Tool": nil,
- "input2": nil,
- "tool2": nil,
- "input3": nil,
+ "dep_fixer": nil,
+ "input": nil,
+ "Implicit": nil,
+ "Input": nil,
+ "OrderOnly": nil,
+ "OrderOnlys": nil,
+ "Tool": nil,
+ "input2": nil,
+ "tool2": nil,
+ "input3": nil,
}
ctx := PathContextForTesting(TestConfig("out", nil, "", fs))
@@ -290,6 +292,7 @@
ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
Input(PathForSource(ctx, "Input")).
Output(PathForOutput(ctx, "Output")).
+ OrderOnly(PathForSource(ctx, "OrderOnly")).
Text("Text").
Tool(PathForSource(ctx, "Tool"))
@@ -298,6 +301,7 @@
DepFile(PathForOutput(ctx, "depfile2")).
Input(PathForSource(ctx, "input2")).
Output(PathForOutput(ctx, "output2")).
+ OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Tool(PathForSource(ctx, "tool2"))
// Test updates to the first command after the second command has been started
@@ -317,6 +321,7 @@
wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"})
wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"})
wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
+ wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
t.Run("normal", func(t *testing.T) {
rule := NewRuleBuilder()
@@ -346,6 +351,9 @@
if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
}
+ if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
+ }
if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
@@ -380,6 +388,9 @@
if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
}
+ if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
+ }
if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index fa1e204..619cf86 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -73,6 +73,9 @@
// feature: {
// cflags: ["-DFEATURE"],
// },
+// width: {
+// cflags: ["-DWIDTH=%s"],
+// },
// },
// }
//
@@ -90,6 +93,7 @@
// config_namespace: "acme",
// variables: ["board"],
// bool_variables: ["feature"],
+// value_variables: ["width"],
// properties: ["cflags", "srcs"],
// }
//
@@ -107,8 +111,9 @@
//
// SOONG_CONFIG_acme_board := soc_a
// SOONG_CONFIG_acme_feature := true
+// SOONG_CONFIG_acme_width := 200
//
-// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE".
+// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
func soongConfigModuleTypeImportFactory() Module {
module := &soongConfigModuleTypeImport{}
@@ -122,7 +127,10 @@
}
func (m *soongConfigModuleTypeImport) Name() string {
- return "soong_config_module_type_import_" + soongconfig.CanonicalizeToProperty(m.properties.From)
+ // The generated name is non-deterministic, but it does not
+ // matter because this module does not emit any rules.
+ return soongconfig.CanonicalizeToProperty(m.properties.From) +
+ "soong_config_module_type_import_" + fmt.Sprintf("%p", m)
}
func (*soongConfigModuleTypeImport) Nameless() {}
@@ -148,6 +156,7 @@
// config_namespace: "acme",
// variables: ["board"],
// bool_variables: ["feature"],
+// value_variables: ["width"],
// properties: ["cflags", "srcs"],
// }
//
@@ -171,6 +180,9 @@
// feature: {
// cflags: ["-DFEATURE"],
// },
+// width: {
+// cflags: ["-DWIDTH=%s"],
+// },
// },
// }
//
@@ -189,6 +201,7 @@
//
// SOONG_CONFIG_acme_board := soc_a
// SOONG_CONFIG_acme_feature := true
+// SOONG_CONFIG_acme_width := 200
//
// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE".
func soongConfigModuleTypeFactory() Module {
@@ -349,7 +362,12 @@
AddLoadHook(module, func(ctx LoadHookContext) {
config := ctx.Config().VendorConfig(moduleType.ConfigNamespace)
- for _, ps := range soongconfig.PropertiesToApply(moduleType, conditionalProps, config) {
+ newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, config)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ return
+ }
+ for _, ps := range newProps {
ctx.AppendProperties(ps)
}
})
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 1cf060d..f905b1a 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -45,6 +45,7 @@
config_namespace: "acme",
variables: ["board", "feature1", "FEATURE3"],
bool_variables: ["feature2"],
+ value_variables: ["size"],
properties: ["cflags", "srcs"],
}
@@ -82,6 +83,9 @@
cflags: ["-DSOC_B"],
},
},
+ size: {
+ cflags: ["-DSIZE=%s"],
+ },
feature1: {
cflags: ["-DFEATURE1"],
},
@@ -101,6 +105,7 @@
config.TestProductVariables.VendorVars = map[string]map[string]string{
"acme": map[string]string{
"board": "soc_a",
+ "size": "42",
"feature1": "true",
"feature2": "false",
// FEATURE3 unset
@@ -121,7 +126,7 @@
FailIfErrored(t, errs)
foo := ctx.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
- if g, w := foo.props.Cflags, []string{"-DGENERIC", "-DSOC_A", "-DFEATURE1"}; !reflect.DeepEqual(g, w) {
+ if g, w := foo.props.Cflags, []string{"-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"}; !reflect.DeepEqual(g, w) {
t.Errorf("wanted foo cflags %q, got %q", w, g)
}
}
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 2d6063d..142a813 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -112,6 +112,10 @@
// the list of boolean SOONG_CONFIG variables that this module type will read
Bool_variables []string
+ // the list of SOONG_CONFIG variables that this module type will read. The value will be
+ // inserted into the properties with %s substitution.
+ Value_variables []string
+
// the list of properties that this module type will extend.
Properties []string
}
@@ -161,6 +165,18 @@
})
}
+ for _, name := range props.Value_variables {
+ if name == "" {
+ return []error{fmt.Errorf("value_variables entry must not be blank")}
+ }
+
+ mt.Variables = append(mt.Variables, &valueVariable{
+ baseVariable: baseVariable{
+ variable: name,
+ },
+ })
+ }
+
return nil
}
@@ -404,15 +420,17 @@
// PropertiesToApply returns the applicable properties from a ModuleType that should be applied
// based on SoongConfig values.
-func PropertiesToApply(moduleType *ModuleType, props reflect.Value, config SoongConfig) []interface{} {
+func PropertiesToApply(moduleType *ModuleType, props reflect.Value, config SoongConfig) ([]interface{}, error) {
var ret []interface{}
props = props.Elem().FieldByName(soongConfigProperty)
for i, c := range moduleType.Variables {
- if ps := c.PropertiesToApply(config, props.Field(i)); ps != nil {
+ if ps, err := c.PropertiesToApply(config, props.Field(i)); err != nil {
+ return nil, err
+ } else if ps != nil {
ret = append(ret, ps)
}
}
- return ret
+ return ret, nil
}
type ModuleType struct {
@@ -438,7 +456,7 @@
// PropertiesToApply should return one of the interface{} values set by initializeProperties to be applied
// to the module.
- PropertiesToApply(config SoongConfig, values reflect.Value) interface{}
+ PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error)
}
type baseVariable struct {
@@ -473,14 +491,14 @@
}
}
-func (s *stringVariable) PropertiesToApply(config SoongConfig, values reflect.Value) interface{} {
+func (s *stringVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
for j, v := range s.values {
if config.String(s.variable) == v {
- return values.Field(j).Interface()
+ return values.Field(j).Interface(), nil
}
}
- return nil
+ return nil, nil
}
type boolVariable struct {
@@ -495,11 +513,83 @@
v.Set(reflect.Zero(typ))
}
-func (b boolVariable) PropertiesToApply(config SoongConfig, values reflect.Value) interface{} {
+func (b boolVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
if config.Bool(b.variable) {
- return values.Interface()
+ return values.Interface(), nil
}
+ return nil, nil
+}
+
+type valueVariable struct {
+ baseVariable
+}
+
+func (s *valueVariable) variableValuesType() reflect.Type {
+ return emptyInterfaceType
+}
+
+func (s *valueVariable) initializeProperties(v reflect.Value, typ reflect.Type) {
+ v.Set(reflect.Zero(typ))
+}
+
+func (s *valueVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
+ if !config.IsSet(s.variable) {
+ return nil, nil
+ }
+ configValue := config.String(s.variable)
+
+ propStruct := values.Elem().Elem()
+ 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()
+ }
+ switch kind {
+ case reflect.String:
+ err := printfIntoProperty(field, configValue)
+ if err != nil {
+ return nil, fmt.Errorf("soong_config_variables.%s.%s: %s", s.variable, propStruct.Type().Field(i).Name, err)
+ }
+ case reflect.Slice:
+ for j := 0; j < field.Len(); j++ {
+ err := printfIntoProperty(field.Index(j), configValue)
+ if err != nil {
+ return nil, fmt.Errorf("soong_config_variables.%s.%s: %s", s.variable, propStruct.Type().Field(i).Name, err)
+ }
+ }
+ case reflect.Bool:
+ // Nothing to do
+ default:
+ return nil, fmt.Errorf("soong_config_variables.%s.%s: unsupported property type %q", s.variable, propStruct.Type().Field(i).Name, kind)
+ }
+ }
+
+ return values.Interface(), nil
+}
+
+func printfIntoProperty(propertyValue reflect.Value, configValue string) error {
+ s := propertyValue.String()
+
+ count := strings.Count(s, "%")
+ if count == 0 {
+ return nil
+ }
+
+ if count > 1 {
+ return fmt.Errorf("value variable properties only support a single '%%'")
+ }
+
+ if !strings.Contains(s, "%s") {
+ return fmt.Errorf("unsupported %% in value variable property")
+ }
+
+ propertyValue.Set(reflect.ValueOf(fmt.Sprintf(s, configValue)))
+
return nil
}
diff --git a/android/variable.go b/android/variable.go
index 4bc3d8a..4d1b5e4 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -140,9 +140,8 @@
// Suffix to add to generated Makefiles
Make_suffix *string `json:",omitempty"`
- BuildId *string `json:",omitempty"`
- BuildNumberFromFile *string `json:",omitempty"`
- DateFromFile *string `json:",omitempty"`
+ BuildId *string `json:",omitempty"`
+ BuildNumberFile *string `json:",omitempty"`
Platform_version_name *string `json:",omitempty"`
Platform_sdk_version *int `json:",omitempty"`
@@ -346,7 +345,7 @@
func (v *productVariables) SetDefaultConfig() {
*v = productVariables{
- BuildNumberFromFile: stringPtr("123456789"),
+ BuildNumberFile: stringPtr("build_number.txt"),
Platform_version_name: stringPtr("Q"),
Platform_sdk_version: intPtr(28),
diff --git a/apex/apex.go b/apex/apex.go
index 3f790dc..d077595 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -345,42 +345,25 @@
"android.hidl.safe_union@1.0",
"bcm_object",
"fmtlib",
- "gemmlowp_headers",
"libarect",
"libbacktrace_headers",
"libbase",
"libbase_headers",
"libbuildversion",
"libc++",
- "libcrypto",
- "libcrypto_static",
"libcutils",
"libcutils_headers",
- "libeigen",
- "libfmq",
- "libhidlbase",
"libhidlbase-impl-internal",
- "libhidlmemory",
"libhidltransport-impl-internal",
"libhwbinder-impl-internal",
- "libjsoncpp",
"liblog_headers",
"libmath",
- "libneuralnetworks_common",
- "libneuralnetworks_headers",
"libprocessgroup",
"libprocessgroup_headers",
"libprocpartition",
"libsync",
"libsystem_headers",
- "libtextclassifier_hash",
- "libtextclassifier_hash_headers",
- "libtextclassifier_hash_static",
- "libtflite_kernel_utils",
"libutils_headers",
- "philox_random",
- "philox_random_headers",
- "tensorflow_headers",
}
//
// Module separator
diff --git a/apex/vndk.go b/apex/vndk.go
index 2a0d5b0..f948d76 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "strconv"
"strings"
"sync"
@@ -121,10 +122,13 @@
// When all hard-coded references are fixed, remove symbolic links
// Note that we should keep following symlinks for older VNDKs (<=29)
// Since prebuilt vndk libs still depend on system/lib/vndk path
- if strings.HasPrefix(name, vndkApexName) {
- vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
- if strings.HasPrefix(name, vndkApexNamePrefix) {
- vndkVersion = strings.TrimPrefix(name, vndkApexNamePrefix)
+ if strings.HasPrefix(name, vndkApexNamePrefix) {
+ vndkVersion := strings.TrimPrefix(name, vndkApexNamePrefix)
+ if numVer, err := strconv.Atoi(vndkVersion); err != nil {
+ ctx.ModuleErrorf("apex_vndk should be named as %v<ver:number>: %s", vndkApexNamePrefix, name)
+ return
+ } else if numVer > android.SdkVersion_Android10 {
+ return
}
// the name of vndk apex is formatted "com.android.vndk.v" + version
apexName := vndkApexNamePrefix + vndkVersion
diff --git a/cc/androidmk.go b/cc/androidmk.go
index ef695b0..1c90aaf 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -248,6 +248,10 @@
entries.SubName = "." + library.stubsVersion()
}
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ // Note library.skipInstall() has a special case to get here for static
+ // libraries that otherwise would have skipped installation and hence not
+ // have executed AndroidMkEntries at all. The reason is to ensure they get
+ // a NOTICE file make target which other libraries might depend on.
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
if library.buildStubs() {
entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
diff --git a/cc/cc.go b/cc/cc.go
index cb71c3b..e4a42a0 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -377,6 +377,7 @@
inSanitizerDir() bool
hostToolPath() android.OptionalPath
relativeInstallPath() string
+ skipInstall(mod *Module)
}
type xref interface {
@@ -2588,6 +2589,14 @@
return c.InRecovery()
}
+func (c *Module) SkipInstall() {
+ if c.installer == nil {
+ c.ModuleBase.SkipInstall()
+ return
+ }
+ c.installer.skipInstall(c)
+}
+
func (c *Module) HostToolPath() android.OptionalPath {
if c.installer == nil {
return android.OptionalPath{}
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 43e8c85..cd0a508 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -58,8 +58,11 @@
"-Wl,--dynamicbase",
"-Wl,--nxcompat",
}
+ windowsLldflags = []string{
+ "-Wl,--Xlink=-Brepro", // Enable deterministic build
+ }
windowsClangLdflags = append(ClangFilterUnknownCflags(windowsLdflags), []string{}...)
- windowsClangLldflags = ClangFilterUnknownLldflags(windowsClangLdflags)
+ windowsClangLldflags = append(ClangFilterUnknownLldflags(windowsClangLdflags), windowsLldflags...)
windowsX86Cflags = []string{
"-m32",
diff --git a/cc/installer.go b/cc/installer.go
index 2f55ac5..13a4119 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -101,3 +101,7 @@
func (installer *baseInstaller) relativeInstallPath() string {
return String(installer.Properties.Relative_install_path)
}
+
+func (installer *baseInstaller) skipInstall(mod *Module) {
+ mod.ModuleBase.SkipInstall()
+}
diff --git a/cc/library.go b/cc/library.go
index c7488ee..34b27a4 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1303,6 +1303,18 @@
return android.CheckAvailableForApex(what, list)
}
+func (library *libraryDecorator) skipInstall(mod *Module) {
+ if library.static() && library.buildStatic() && !library.buildStubs() {
+ // If we're asked to skip installation of a static library (in particular
+ // when it's not //apex_available:platform) we still want an AndroidMk entry
+ // for it to ensure we get the relevant NOTICE file targets (cf.
+ // notice_files.mk) that other libraries might depend on. AndroidMkEntries
+ // always sets LOCAL_UNINSTALLABLE_MODULE for these entries.
+ return
+ }
+ mod.ModuleBase.SkipInstall()
+}
+
var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
func versioningMacroNamesList(config android.Config) *map[string]string {
diff --git a/cc/linker.go b/cc/linker.go
index af4cbf3..a7b621a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -501,19 +501,21 @@
var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol",
blueprint.RuleParams{
Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " +
- "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $buildNumberFromFile",
+ "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $$(cat $buildNumberFile)",
CommandDeps: []string{"$symbolInjectCmd"},
},
- "buildNumberFromFile")
+ "buildNumberFile")
func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) {
+ buildNumberFile := ctx.Config().BuildNumberFile(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: injectVersionSymbol,
Description: "inject version symbol",
Input: in,
Output: out,
+ OrderOnly: android.Paths{buildNumberFile},
Args: map[string]string{
- "buildNumberFromFile": proptools.NinjaEscape(ctx.Config().BuildNumberFromFile()),
+ "buildNumberFile": buildNumberFile.String(),
},
})
}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index b0cf489..4f77d41 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -134,6 +134,10 @@
p.properties.Srcs = nil
}
+func (p *prebuiltLibraryLinker) skipInstall(mod *Module) {
+ mod.ModuleBase.SkipInstall()
+}
+
func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module, library := NewLibrary(hod)
module.compiler = nil
@@ -142,6 +146,7 @@
libraryDecorator: library,
}
module.linker = prebuilt
+ module.installer = prebuilt
module.AddProperties(&prebuilt.properties)
diff --git a/cc/vndk.go b/cc/vndk.go
index 29af9a7..8eab8ba 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -309,6 +309,10 @@
panic(err)
}
+ if m.HasStubsVariants() {
+ mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK")
+ }
+
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
diff --git a/java/app.go b/java/app.go
index c64f1f7..1ad81fe 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1345,6 +1345,12 @@
// if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
// Defaults to sdk_version if not set.
Min_sdk_version *string
+
+ // list of android_library modules whose resources are extracted and linked against statically
+ Static_libs []string
+
+ // list of android_app modules whose resources are extracted and linked against
+ Resource_libs []string
}
func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1357,6 +1363,9 @@
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+
+ ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
+ ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
}
func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
diff --git a/java/app_test.go b/java/app_test.go
index 10503e7..c259fe2 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2342,11 +2342,17 @@
}
func TestRuntimeResourceOverlay(t *testing.T) {
- ctx, config := testJava(t, `
+ fs := map[string][]byte{
+ "baz/res/res/values/strings.xml": nil,
+ "bar/res/res/values/strings.xml": nil,
+ }
+ bp := `
runtime_resource_overlay {
name: "foo",
certificate: "platform",
product_specific: true,
+ static_libs: ["bar"],
+ resource_libs: ["baz"],
aaptflags: ["--keep-raw-values"],
}
@@ -2356,7 +2362,21 @@
product_specific: true,
theme: "faza",
}
- `)
+
+ android_library {
+ name: "bar",
+ resource_dirs: ["bar/res"],
+ }
+
+ android_app {
+ name: "baz",
+ sdk_version: "current",
+ resource_dirs: ["baz/res"],
+ }
+ `
+ config := testAppConfig(nil, bp, fs)
+ ctx := testContext()
+ run(t, ctx, config)
m := ctx.ModuleForTests("foo", "android_common")
@@ -2368,6 +2388,19 @@
t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
}
+ // Check overlay.list output for static_libs dependency.
+ overlayList := m.Output("aapt2/overlay.list").Inputs.Strings()
+ staticLibPackage := buildDir + "/.intermediates/bar/android_common/package-res.apk"
+ if !inList(staticLibPackage, overlayList) {
+ t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList)
+ }
+
+ // Check AAPT2 link flags for resource_libs dependency.
+ resourceLibFlag := "-I " + buildDir + "/.intermediates/baz/android_common/package-res.apk"
+ if !strings.Contains(aapt2Flags, resourceLibFlag) {
+ t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags)
+ }
+
// Check cert signing flag.
signedApk := m.Output("signed/foo.apk")
signingFlag := signedApk.Args["certificates"]
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 70d997a..1ac7444 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -773,6 +773,7 @@
}
func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, docletPath classpath) {
+ buildNumberFile := ctx.Config().BuildNumberFile(ctx)
// Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9
// sources, droiddoc will get sources produced by metalava which will have already stripped out the
// 1.9 language features.
@@ -782,7 +783,7 @@
Flag("-XDignore.symbol.file").
FlagWithArg("-doclet ", "com.google.doclava.Doclava").
FlagWithInputList("-docletpath ", docletPath.Paths(), ":").
- FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-"+ctx.Config().BuildNumberFromFile()).
+ FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-$(cat "+buildNumberFile.String()+")").OrderOnly(buildNumberFile).
FlagWithArg("-hdf page.now ", `"$(date -d @$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `)
if String(d.properties.Custom_template) == "" {
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index cb17fee..86eddb1 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -28,10 +28,6 @@
func RegisterPrebuiltApisBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("prebuilt_apis", PrebuiltApisFactory)
-
- ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("prebuilt_apis", PrebuiltApisMutator).Parallel()
- })
}
type prebuiltApisProperties struct {
@@ -48,7 +44,7 @@
// no need to implement
}
-func parseJarPath(ctx android.BaseModuleContext, path string) (module string, apiver string, scope string) {
+func parseJarPath(path string) (module string, apiver string, scope string) {
elements := strings.Split(path, "/")
apiver = elements[0]
@@ -58,7 +54,7 @@
return
}
-func parseApiFilePath(ctx android.BaseModuleContext, path string) (module string, apiver string, scope string) {
+func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, apiver string, scope string) {
elements := strings.Split(path, "/")
apiver = elements[0]
@@ -73,7 +69,7 @@
return
}
-func createImport(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
+func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
props := struct {
Name *string
Jars []string
@@ -89,7 +85,7 @@
mctx.CreateModule(ImportFactory, &props)
}
-func createFilegroup(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
+func createFilegroup(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
fgName := module + ".api." + scope + "." + apiver
filegroupProps := struct {
Name *string
@@ -100,7 +96,7 @@
mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
}
-func getPrebuiltFiles(mctx android.TopDownMutatorContext, name string) []string {
+func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string {
mydir := mctx.ModuleDir() + "/"
var files []string
for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs {
@@ -115,7 +111,7 @@
return files
}
-func prebuiltSdkStubs(mctx android.TopDownMutatorContext) {
+func prebuiltSdkStubs(mctx android.LoadHookContext) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/<module>.jar
files := getPrebuiltFiles(mctx, "*.jar")
@@ -123,12 +119,12 @@
for _, f := range files {
// create a Import module for each jar file
localPath := strings.TrimPrefix(f, mydir)
- module, apiver, scope := parseJarPath(mctx, localPath)
+ module, apiver, scope := parseJarPath(localPath)
createImport(mctx, module, scope, apiver, localPath)
}
}
-func prebuiltApiFiles(mctx android.TopDownMutatorContext) {
+func prebuiltApiFiles(mctx android.LoadHookContext) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/api/<module>.txt
files := getPrebuiltFiles(mctx, "api/*.txt")
@@ -178,7 +174,7 @@
}
}
-func PrebuiltApisMutator(mctx android.TopDownMutatorContext) {
+func createPrebuiltApiModules(mctx android.LoadHookContext) {
if _, ok := mctx.Module().(*prebuiltApis); ok {
prebuiltApiFiles(mctx)
prebuiltSdkStubs(mctx)
@@ -191,9 +187,15 @@
// generates a filegroup module named <module>-api.<scope>.<ver>.
//
// It also creates <module>-api.<scope>.latest for the latest <ver>.
+//
+// Similarly, it generates a java_import for all API .jar files found under the
+// directory where the Android.bp is located. Specifically, an API file located
+// at ./<ver>/<scope>/api/<module>.jar generates a java_import module named
+// <prebuilt-api-module>.<scope>.<ver>.<module>.
func PrebuiltApisFactory() android.Module {
module := &prebuiltApis{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
+ android.AddLoadHook(module, createPrebuiltApiModules)
return module
}