Merge "Add BUILD_BROKEN_PREBUILT_ELF_FILES to dumpvars.go"
diff --git a/Android.bp b/Android.bp
index 25038c6..1dfac87 100644
--- a/Android.bp
+++ b/Android.bp
@@ -67,6 +67,7 @@
"android/proto.go",
"android/register.go",
"android/rule_builder.go",
+ "android/sdk.go",
"android/sh_binary.go",
"android/singleton.go",
"android/testing.go",
@@ -171,6 +172,7 @@
"cc/vndk_prebuilt.go",
"cc/xom.go",
+ "cc/cflag_artifacts.go",
"cc/cmakelists.go",
"cc/compdb.go",
"cc/compiler.go",
@@ -303,7 +305,6 @@
"java/jdeps_test.go",
"java/kotlin_test.go",
"java/plugin_test.go",
- "java/robolectric_test.go",
"java/sdk_test.go",
],
pluginFor: ["soong_build"],
@@ -332,8 +333,11 @@
"soong-cc-config",
],
srcs: [
+ "rust/config/arm_device.go",
+ "rust/config/arm64_device.go",
"rust/config/global.go",
"rust/config/toolchain.go",
+ "rust/config/whitelist.go",
"rust/config/x86_linux_host.go",
"rust/config/x86_64_device.go",
],
@@ -474,6 +478,26 @@
pluginFor: ["soong_build"],
}
+bootstrap_go_package {
+ name: "soong-sdk",
+ pkgPath: "android/soong/sdk",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-apex",
+ "soong-cc",
+ "soong-java",
+ ],
+ srcs: [
+ "sdk/sdk.go",
+ ],
+ testSrcs: [
+ "sdk/sdk_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
+
//
// Defaults to enable various configurations of host bionic
//
diff --git a/OWNERS b/OWNERS
index 4ae045d..797229f 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,4 @@
per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
per-file tidy.go = srhines@google.com, chh@google.com
per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+per-file rust/config/whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/android/androidmk.go b/android/androidmk.go
index 124523f..9071347 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -80,12 +80,14 @@
footer bytes.Buffer
ExtraEntries []AndroidMkExtraEntriesFunc
+ ExtraFooters []AndroidMkExtraFootersFunc
EntryMap map[string][]string
entryOrder []string
}
type AndroidMkExtraEntriesFunc func(entries *AndroidMkEntries)
+type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string, entries *AndroidMkEntries)
func (a *AndroidMkEntries) SetString(name, value string) {
if _, ok := a.EntryMap[name]; !ok {
@@ -94,6 +96,13 @@
a.EntryMap[name] = []string{value}
}
+func (a *AndroidMkEntries) SetPath(name string, path Path) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.entryOrder = append(a.entryOrder, name)
+ }
+ a.EntryMap[name] = []string{path.String()}
+}
+
func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
if flag {
if _, ok := a.EntryMap[name]; !ok {
@@ -103,6 +112,17 @@
}
}
+func (a *AndroidMkEntries) SetBool(name string, flag bool) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.entryOrder = append(a.entryOrder, name)
+ }
+ if flag {
+ a.EntryMap[name] = []string{"true"}
+ } else {
+ a.EntryMap[name] = []string{"false"}
+ }
+}
+
func (a *AndroidMkEntries) AddStrings(name string, value ...string) {
if len(value) == 0 {
return
@@ -254,9 +274,21 @@
// Write to footer.
fmt.Fprintln(&a.footer, "include "+a.Include)
+ blueprintDir := filepath.Dir(bpPath)
+ for _, footerFunc := range a.ExtraFooters {
+ footerFunc(&a.footer, name, prefix, blueprintDir, a)
+ }
}
func (a *AndroidMkEntries) write(w io.Writer) {
+ if a.Disabled {
+ return
+ }
+
+ if !a.OutputFile.Valid() {
+ return
+ }
+
w.Write(a.header.Bytes())
for _, name := range a.entryOrder {
fmt.Fprintln(w, name+" := "+strings.Join(a.EntryMap[name], " "))
@@ -264,6 +296,10 @@
w.Write(a.footer.Bytes())
}
+func (a *AndroidMkEntries) FooterLinesForTests() []string {
+ return strings.Split(string(a.footer.Bytes()), "\n")
+}
+
func AndroidMkSingleton() Singleton {
return &androidMkSingleton{}
}
diff --git a/android/apex.go b/android/apex.go
index 99b13ab..557febf 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -78,12 +78,23 @@
// Return the no_apex property
NoApex() bool
+
+ // Tests if this module is available for the specified APEX or ":platform"
+ AvailableFor(what string) bool
}
type ApexProperties struct {
// Whether this module should not be part of any APEX. Default is false.
+ // TODO(b/128708192): remove this as this is equal to apex_available: [":platform"]
No_apex *bool
+ // Availability of this module in APEXes. Only the listed APEXes can include this module.
+ // "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
+ // "//apex_available:platform" refers to non-APEX partitions like "system.img".
+ // Default is ["//apex_available:platform", "//apex_available:anyapex"].
+ // TODO(b/128708192) change the default to ["//apex_available:platform"]
+ Apex_available []string
+
// Name of the apex variant that this module is mutated into
ApexName string `blueprint:"mutated"`
}
@@ -136,15 +147,46 @@
return proptools.Bool(m.ApexProperties.No_apex)
}
+const (
+ availableToPlatform = "//apex_available:platform"
+ availableToAnyApex = "//apex_available:anyapex"
+)
+
+func (m *ApexModuleBase) AvailableFor(what string) bool {
+ if len(m.ApexProperties.Apex_available) == 0 {
+ // apex_available defaults to ["//apex_available:platform", "//apex_available:anyapex"],
+ // which means 'available to everybody'.
+ return true
+ }
+ return InList(what, m.ApexProperties.Apex_available) ||
+ (what != availableToPlatform && InList(availableToAnyApex, m.ApexProperties.Apex_available))
+}
+
+func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
+ for _, n := range m.ApexProperties.Apex_available {
+ if n == availableToPlatform || n == availableToAnyApex {
+ continue
+ }
+ if !mctx.OtherModuleExists(n) {
+ mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
+ }
+ }
+}
+
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module {
if len(m.apexVariations) > 0 {
+ m.checkApexAvailableProperty(mctx)
sort.Strings(m.apexVariations)
- variations := []string{""} // Original variation for platform
+ variations := []string{}
+ availableForPlatform := m.AvailableFor(availableToPlatform)
+ if availableForPlatform {
+ variations = append(variations, "") // Original variation for platform
+ }
variations = append(variations, m.apexVariations...)
modules := mctx.CreateVariations(variations...)
for i, m := range modules {
- if i == 0 {
+ if availableForPlatform && i == 0 {
continue
}
m.(ApexModule).setApexName(variations[i])
diff --git a/android/arch.go b/android/arch.go
index 907c58b..b5b52a9 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -855,149 +855,11 @@
}
}
-func filterArchStructFields(fields []reflect.StructField) (filteredFields []reflect.StructField, filtered bool) {
- for _, field := range fields {
- if !proptools.HasTag(field, "android", "arch_variant") {
- filtered = true
- continue
- }
-
- // The arch_variant field isn't necessary past this point
- // Instead of wasting space, just remove it. Go also has a
- // 16-bit limit on structure name length. The name is constructed
- // based on the Go source representation of the structure, so
- // the tag names count towards that length.
- //
- // TODO: handle the uncommon case of other tags being involved
- if field.Tag == `android:"arch_variant"` {
- field.Tag = ""
- }
-
- // Recurse into structs
- switch field.Type.Kind() {
- case reflect.Struct:
- var subFiltered bool
- field.Type, subFiltered = filterArchStruct(field.Type)
- filtered = filtered || subFiltered
- if field.Type == nil {
- continue
- }
- case reflect.Ptr:
- if field.Type.Elem().Kind() == reflect.Struct {
- nestedType, subFiltered := filterArchStruct(field.Type.Elem())
- filtered = filtered || subFiltered
- if nestedType == nil {
- continue
- }
- field.Type = reflect.PtrTo(nestedType)
- }
- case reflect.Interface:
- panic("Interfaces are not supported in arch_variant properties")
- }
-
- filteredFields = append(filteredFields, field)
- }
-
- return filteredFields, filtered
-}
-
-// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a reflect.Type
-// that only contains the fields in the original type that have an `android:"arch_variant"` struct tag, and a bool
-// that is true if the new struct type has fewer fields than the original type. If there are no fields in the
-// original type with the struct tag it returns nil and true.
-func filterArchStruct(prop reflect.Type) (filteredProp reflect.Type, filtered bool) {
- var fields []reflect.StructField
-
- ptr := prop.Kind() == reflect.Ptr
- if ptr {
- prop = prop.Elem()
- }
-
- for i := 0; i < prop.NumField(); i++ {
- fields = append(fields, prop.Field(i))
- }
-
- filteredFields, filtered := filterArchStructFields(fields)
-
- if len(filteredFields) == 0 {
- return nil, true
- }
-
- if !filtered {
- if ptr {
- return reflect.PtrTo(prop), false
- }
- return prop, false
- }
-
- ret := reflect.StructOf(filteredFields)
- if ptr {
- ret = reflect.PtrTo(ret)
- }
-
- return ret, true
-}
-
-// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a list of
-// reflect.Type that only contains the fields in the original type that have an `android:"arch_variant"` struct tag,
-// and a bool that is true if the new struct type has fewer fields than the original type. If there are no fields in
-// the original type with the struct tag it returns nil and true. Each returned struct type will have a maximum of
-// 10 top level fields in it to attempt to avoid hitting the reflect.StructOf name length limit, although the limit
-// can still be reached with a single struct field with many fields in it.
-func filterArchStructSharded(prop reflect.Type) (filteredProp []reflect.Type, filtered bool) {
- var fields []reflect.StructField
-
- ptr := prop.Kind() == reflect.Ptr
- if ptr {
- prop = prop.Elem()
- }
-
- for i := 0; i < prop.NumField(); i++ {
- fields = append(fields, prop.Field(i))
- }
-
- fields, filtered = filterArchStructFields(fields)
- if !filtered {
- if ptr {
- return []reflect.Type{reflect.PtrTo(prop)}, false
- }
- return []reflect.Type{prop}, false
- }
-
- if len(fields) == 0 {
- return nil, true
- }
-
- shards := shardFields(fields, 10)
-
- for _, shard := range shards {
- s := reflect.StructOf(shard)
- if ptr {
- s = reflect.PtrTo(s)
- }
- filteredProp = append(filteredProp, s)
- }
-
- return filteredProp, true
-}
-
-func shardFields(fields []reflect.StructField, shardSize int) [][]reflect.StructField {
- ret := make([][]reflect.StructField, 0, (len(fields)+shardSize-1)/shardSize)
- for len(fields) > shardSize {
- ret = append(ret, fields[0:shardSize])
- fields = fields[shardSize:]
- }
- if len(fields) > 0 {
- ret = append(ret, fields)
- }
- return ret
-}
-
// createArchType takes a reflect.Type that is either a struct or a pointer to a struct, and returns a list of
// reflect.Type that contains the arch-variant properties inside structs for each architecture, os, target, multilib,
// etc.
func createArchType(props reflect.Type) []reflect.Type {
- propShards, _ := filterArchStructSharded(props)
+ propShards, _ := proptools.FilterPropertyStructSharded(props, filterArchStruct)
if len(propShards) == 0 {
return nil
}
@@ -1096,6 +958,23 @@
return ret
}
+func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.StructField) {
+ if proptools.HasTag(field, "android", "arch_variant") {
+ // The arch_variant field isn't necessary past this point
+ // Instead of wasting space, just remove it. Go also has a
+ // 16-bit limit on structure name length. The name is constructed
+ // based on the Go source representation of the structure, so
+ // the tag names count towards that length.
+ //
+ // TODO: handle the uncommon case of other tags being involved
+ if field.Tag == `android:"arch_variant"` {
+ field.Tag = ""
+ }
+ return true, field
+ }
+ return false, field
+}
+
var archPropTypeMap OncePer
func InitArchModule(m Module) {
diff --git a/android/arch_test.go b/android/arch_test.go
index 0589e6c..11edb4f 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -17,6 +17,8 @@
import (
"reflect"
"testing"
+
+ "github.com/google/blueprint/proptools"
)
type Named struct {
@@ -219,7 +221,7 @@
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- out, filtered := filterArchStruct(reflect.TypeOf(test.in))
+ out, filtered := proptools.FilterPropertyStruct(reflect.TypeOf(test.in), filterArchStruct)
if filtered != test.filtered {
t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
}
diff --git a/android/config.go b/android/config.go
index cb1bdf5..d03d38e 100644
--- a/android/config.go
+++ b/android/config.go
@@ -800,7 +800,7 @@
func (c *config) EnforceRROForModule(name string) bool {
enforceList := c.productVariables.EnforceRROTargets
if enforceList != nil {
- if len(enforceList) == 1 && (enforceList)[0] == "*" {
+ if InList("*", enforceList) {
return true
}
return InList(name, enforceList)
diff --git a/android/hooks.go b/android/hooks.go
index 5810996..1e5ff21 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -30,7 +30,7 @@
BaseModuleContext
AppendProperties(...interface{})
PrependProperties(...interface{})
- CreateModule(blueprint.ModuleFactory, ...interface{})
+ CreateModule(ModuleFactory, ...interface{}) Module
}
// Arch hooks are run after the module has been split into architecture variants, and can be used
diff --git a/android/module.go b/android/module.go
index dda526f..a1a01a5 100644
--- a/android/module.go
+++ b/android/module.go
@@ -154,6 +154,7 @@
CheckbuildFile(srcPath Path)
InstallInData() bool
+ InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
InstallBypassMake() bool
@@ -192,6 +193,7 @@
Enabled() bool
Target() Target
InstallInData() bool
+ InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
InstallBypassMake() bool
@@ -832,6 +834,10 @@
return false
}
+func (m *ModuleBase) InstallInTestcases() bool {
+ return false
+}
+
func (m *ModuleBase) InstallInSanitizerDir() bool {
return false
}
@@ -1495,10 +1501,19 @@
m.commonProperties.Native_bridge_supported = boolPtr(true)
}
+// IsNativeBridgeSupported returns true if "native_bridge_supported" is explicitly set as "true"
+func (m *ModuleBase) IsNativeBridgeSupported() bool {
+ return proptools.Bool(m.commonProperties.Native_bridge_supported)
+}
+
func (m *moduleContext) InstallInData() bool {
return m.module.InstallInData()
}
+func (m *moduleContext) InstallInTestcases() bool {
+ return m.module.InstallInTestcases()
+}
+
func (m *moduleContext) InstallInSanitizerDir() bool {
return m.module.InstallInSanitizerDir()
}
diff --git a/android/mutator.go b/android/mutator.go
index e76f847..510e63c 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -121,7 +121,7 @@
Rename(name string)
- CreateModule(blueprint.ModuleFactory, ...interface{})
+ CreateModule(ModuleFactory, ...interface{}) Module
}
type topDownMutatorContext struct {
@@ -243,9 +243,10 @@
t.Module().base().commonProperties.DebugName = name
}
-func (t *topDownMutatorContext) CreateModule(factory blueprint.ModuleFactory, props ...interface{}) {
+func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
inherited := []interface{}{&t.Module().base().commonProperties, &t.Module().base().variableProperties}
- t.bp.CreateModule(factory, append(inherited, props...)...)
+ module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), append(inherited, props...)...).(Module)
+ return module
}
func (b *bottomUpMutatorContext) MutatorName() string {
diff --git a/android/paths.go b/android/paths.go
index 0d64a61..8bd2c61 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -44,6 +44,7 @@
BaseModuleContext
InstallInData() bool
+ InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
InstallBypassMake() bool
@@ -1155,6 +1156,8 @@
var partition string
if ctx.InstallInData() {
partition = "data"
+ } else if ctx.InstallInTestcases() {
+ partition = "testcases"
} else if ctx.InstallInRecovery() {
// the layout of recovery partion is the same as that of system partition
partition = "recovery/root/system"
diff --git a/android/paths_test.go b/android/paths_test.go
index f2996bf..b66eb1e 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -201,6 +201,7 @@
baseModuleContext
inData bool
+ inTestcases bool
inSanitizerDir bool
inRecovery bool
}
@@ -219,6 +220,10 @@
return m.inData
}
+func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
+ return m.inTestcases
+}
+
func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
return m.inSanitizerDir
}
diff --git a/android/sdk.go b/android/sdk.go
new file mode 100644
index 0000000..52c392f
--- /dev/null
+++ b/android/sdk.go
@@ -0,0 +1,146 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// 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 (
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+)
+
+// SdkAware is the interface that must be supported by any module to become a member of SDK or to be
+// built with SDK
+type SdkAware interface {
+ Module
+ sdkBase() *SdkBase
+ MakeMemberOf(sdk SdkRef)
+ IsInAnySdk() bool
+ ContainingSdk() SdkRef
+ MemberName() string
+ BuildWithSdks(sdks SdkRefs)
+ RequiredSdks() SdkRefs
+}
+
+// SdkRef refers to a version of an SDK
+type SdkRef struct {
+ Name string
+ Version string
+}
+
+const (
+ // currentVersion refers to the in-development version of an SDK
+ currentVersion = "current"
+)
+
+// IsCurrentVersion determines if the SdkRef is referencing to an in-development version of an SDK
+func (s SdkRef) IsCurrentVersion() bool {
+ return s.Version == currentVersion
+}
+
+// IsCurrentVersionOf determines if the SdkRef is referencing to an in-development version of the
+// specified SDK
+func (s SdkRef) IsCurrentVersionOf(name string) bool {
+ return s.Name == name && s.IsCurrentVersion()
+}
+
+// ParseSdkRef parses a `name#version` style string into a corresponding SdkRef struct
+func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {
+ tokens := strings.Split(str, "#")
+ if len(tokens) < 1 || len(tokens) > 2 {
+ ctx.PropertyErrorf(property, "%q does not follow name#version syntax", str)
+ return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"}
+ }
+
+ name := tokens[0]
+
+ version := currentVersion // If version is omitted, defaults to "current"
+ if len(tokens) == 2 {
+ version = tokens[1]
+ }
+
+ return SdkRef{Name: name, Version: version}
+}
+
+type SdkRefs []SdkRef
+
+func (refs SdkRefs) Contains(s SdkRef) bool {
+ for _, r := range refs {
+ if r == s {
+ return true
+ }
+ }
+ return false
+}
+
+type sdkProperties struct {
+ // The SDK that this module is a member of. nil if it is not a member of any SDK
+ ContainingSdk *SdkRef `blueprint:"mutated"`
+
+ // The list of SDK names and versions that are used to build this module
+ RequiredSdks SdkRefs `blueprint:"mutated"`
+
+ // Name of the module that this sdk member is representing
+ Sdk_member_name *string
+}
+
+// SdkBase is a struct that is expected to be included in module types to implement the SdkAware
+// interface. InitSdkAwareModule should be called to initialize this struct.
+type SdkBase struct {
+ properties sdkProperties
+}
+
+func (s *SdkBase) sdkBase() *SdkBase {
+ return s
+}
+
+// MakeMemberof sets this module to be a member of a specific SDK
+func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
+ s.properties.ContainingSdk = &sdk
+}
+
+// IsInAnySdk returns true if this module is a member of any SDK
+func (s *SdkBase) IsInAnySdk() bool {
+ return s.properties.ContainingSdk != nil
+}
+
+// ContainingSdk returns the SDK that this module is a member of
+func (s *SdkBase) ContainingSdk() SdkRef {
+ if s.properties.ContainingSdk != nil {
+ return *s.properties.ContainingSdk
+ }
+ return SdkRef{Name: "", Version: currentVersion}
+}
+
+// Membername returns the name of the module that this SDK member is overriding
+func (s *SdkBase) MemberName() string {
+ return proptools.String(s.properties.Sdk_member_name)
+}
+
+// BuildWithSdks is used to mark that this module has to be built with the given SDK(s).
+func (s *SdkBase) BuildWithSdks(sdks SdkRefs) {
+ s.properties.RequiredSdks = sdks
+}
+
+// RequiredSdks returns the SDK(s) that this module has to be built with
+func (s *SdkBase) RequiredSdks() SdkRefs {
+ return s.properties.RequiredSdks
+}
+
+// InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including
+// SdkBase.
+func InitSdkAwareModule(m SdkAware) {
+ base := m.sdkBase()
+ m.AddProperties(&base.properties)
+}
diff --git a/android/util.go b/android/util.go
index 0102442..71ded5e 100644
--- a/android/util.go
+++ b/android/util.go
@@ -319,3 +319,36 @@
return root, suffix, ext
}
+
+// ShardPaths takes a Paths, and returns a slice of Paths where each one has at most shardSize paths.
+func ShardPaths(paths Paths, shardSize int) []Paths {
+ if len(paths) == 0 {
+ return nil
+ }
+ ret := make([]Paths, 0, (len(paths)+shardSize-1)/shardSize)
+ for len(paths) > shardSize {
+ ret = append(ret, paths[0:shardSize])
+ paths = paths[shardSize:]
+ }
+ if len(paths) > 0 {
+ ret = append(ret, paths)
+ }
+ return ret
+}
+
+// ShardStrings takes a slice of strings, and returns a slice of slices of strings where each one has at most shardSize
+// elements.
+func ShardStrings(s []string, shardSize int) [][]string {
+ if len(s) == 0 {
+ return nil
+ }
+ ret := make([][]string, 0, (len(s)+shardSize-1)/shardSize)
+ for len(s) > shardSize {
+ ret = append(ret, s[0:shardSize])
+ s = s[shardSize:]
+ }
+ if len(s) > 0 {
+ ret = append(ret, s)
+ }
+ return ret
+}
diff --git a/android/util_test.go b/android/util_test.go
index 1df1c5a..90fefee 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -469,3 +469,102 @@
}
})
}
+
+func Test_Shard(t *testing.T) {
+ type args struct {
+ strings []string
+ shardSize int
+ }
+ tests := []struct {
+ name string
+ args args
+ want [][]string
+ }{
+ {
+ name: "empty",
+ args: args{
+ strings: nil,
+ shardSize: 1,
+ },
+ want: [][]string(nil),
+ },
+ {
+ name: "single shard",
+ args: args{
+ strings: []string{"a", "b"},
+ shardSize: 2,
+ },
+ want: [][]string{{"a", "b"}},
+ },
+ {
+ name: "single short shard",
+ args: args{
+ strings: []string{"a", "b"},
+ shardSize: 3,
+ },
+ want: [][]string{{"a", "b"}},
+ },
+ {
+ name: "shard per input",
+ args: args{
+ strings: []string{"a", "b", "c"},
+ shardSize: 1,
+ },
+ want: [][]string{{"a"}, {"b"}, {"c"}},
+ },
+ {
+ name: "balanced shards",
+ args: args{
+ strings: []string{"a", "b", "c", "d"},
+ shardSize: 2,
+ },
+ want: [][]string{{"a", "b"}, {"c", "d"}},
+ },
+ {
+ name: "unbalanced shards",
+ args: args{
+ strings: []string{"a", "b", "c"},
+ shardSize: 2,
+ },
+ want: [][]string{{"a", "b"}, {"c"}},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Run("strings", func(t *testing.T) {
+ if got := ShardStrings(tt.args.strings, tt.args.shardSize); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("ShardStrings(%v, %v) = %v, want %v",
+ tt.args.strings, tt.args.shardSize, got, tt.want)
+ }
+ })
+
+ t.Run("paths", func(t *testing.T) {
+ stringsToPaths := func(strings []string) Paths {
+ if strings == nil {
+ return nil
+ }
+ paths := make(Paths, len(strings))
+ for i, s := range strings {
+ paths[i] = PathForTesting(s)
+ }
+ return paths
+ }
+
+ paths := stringsToPaths(tt.args.strings)
+
+ var want []Paths
+ if sWant := tt.want; sWant != nil {
+ want = make([]Paths, len(sWant))
+ for i, w := range sWant {
+ want[i] = stringsToPaths(w)
+ }
+ }
+
+ if got := ShardPaths(paths, tt.args.shardSize); !reflect.DeepEqual(got, want) {
+ t.Errorf("ShardPaths(%v, %v) = %v, want %v",
+ paths, tt.args.shardSize, got, want)
+ }
+ })
+ })
+ }
+}
diff --git a/apex/apex.go b/apex/apex.go
index fb4497b..aff8d50 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -21,6 +21,7 @@
"runtime"
"sort"
"strings"
+ "sync"
"android/soong/android"
"android/soong/cc"
@@ -46,13 +47,15 @@
Description: "fs_config ${out}",
}, "ro_paths", "exec_paths")
- injectApexDependency = pctx.StaticRule("injectApexDependency", blueprint.RuleParams{
+ apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{
Command: `rm -f $out && ${jsonmodify} $in ` +
`-a provideNativeLibs ${provideNativeLibs} ` +
- `-a requireNativeLibs ${requireNativeLibs} -o $out`,
+ `-a requireNativeLibs ${requireNativeLibs} ` +
+ `${opt} ` +
+ `-o $out`,
CommandDeps: []string{"${jsonmodify}"},
- Description: "Inject dependency into ${out}",
- }, "provideNativeLibs", "requireNativeLibs")
+ Description: "prepare ${out}",
+ }, "provideNativeLibs", "requireNativeLibs", "opt")
// TODO(b/113233103): make sure that file_contexts is sane, i.e., validate
// against the binary policy using sefcontext_compiler -p <policy>.
@@ -149,10 +152,9 @@
var (
whitelistNoApex = map[string][]string{
"apex_test_build_features": []string{"libbinder"},
- "com.android.neuralnetworks": []string{"libbinder"},
- "com.android.media": []string{"libbinder"},
"com.android.media.swcodec": []string{"libbinder"},
"test_com.android.media.swcodec": []string{"libbinder"},
+ "com.android.vndk": []string{"libbinder"},
}
)
@@ -183,17 +185,69 @@
pctx.HostBinToolVariable("zipalign", "zipalign")
pctx.HostBinToolVariable("jsonmodify", "jsonmodify")
- android.RegisterModuleType("apex", apexBundleFactory)
+ android.RegisterModuleType("apex", BundleFactory)
android.RegisterModuleType("apex_test", testApexBundleFactory)
+ android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
android.RegisterModuleType("apex_defaults", defaultsFactory)
android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_deps", apexDepsMutator)
- ctx.BottomUp("apex", apexMutator).Parallel()
- ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
- ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
+ android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator).Parallel()
+ ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator).Parallel()
})
+ android.PostDepsMutators(RegisterPostDepsMutators)
+}
+
+func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_deps", apexDepsMutator)
+ ctx.BottomUp("apex", apexMutator).Parallel()
+ ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
+ ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
+}
+
+var (
+ vndkApexListKey = android.NewOnceKey("vndkApexList")
+ vndkApexListMutex sync.Mutex
+)
+
+func vndkApexList(config android.Config) map[string]*apexBundle {
+ return config.Once(vndkApexListKey, func() interface{} {
+ return map[string]*apexBundle{}
+ }).(map[string]*apexBundle)
+}
+
+// apexVndkGatherMutator gathers "apex_vndk" modules and puts them in a map with vndk_version as a key.
+func apexVndkGatherMutator(mctx android.TopDownMutatorContext) {
+ if ab, ok := mctx.Module().(*apexBundle); ok && ab.vndkApex {
+ if ab.IsNativeBridgeSupported() {
+ mctx.PropertyErrorf("native_bridge_supported", "%q doesn't support native bridge binary.", mctx.ModuleType())
+ }
+ vndkVersion := proptools.StringDefault(ab.vndkProperties.Vndk_version, mctx.DeviceConfig().PlatformVndkVersion())
+ vndkApexListMutex.Lock()
+ defer vndkApexListMutex.Unlock()
+ vndkApexList := vndkApexList(mctx.Config())
+ if other, ok := vndkApexList[vndkVersion]; ok {
+ mctx.PropertyErrorf("vndk_version", "%v is already defined in %q", vndkVersion, other.Name())
+ }
+ vndkApexList[vndkVersion] = ab
+ }
+}
+
+// apexVndkAddDepsMutator adds (reverse) dependencies from vndk libs to apex_vndk modules.
+// It filters only libs with matching targets.
+func apexVndkAddDepsMutator(mctx android.BottomUpMutatorContext) {
+ if cc, ok := mctx.Module().(*cc.Module); ok && cc.IsVndkOnSystem() {
+ vndkApexList := vndkApexList(mctx.Config())
+ if ab, ok := vndkApexList[cc.VndkVersion()]; ok {
+ targetArch := cc.Target().String()
+ for _, target := range ab.MultiTargets() {
+ if target.String() == targetArch {
+ mctx.AddReverseDependency(mctx.Module(), sharedLibTag, ab.Name())
+ break
+ }
+ }
+ }
+ }
}
// Mark the direct and transitive dependencies of apex bundles so that they
@@ -235,11 +289,14 @@
}
func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
- if _, ok := mctx.Module().(*apexBundle); ok {
+ if ab, ok := mctx.Module().(*apexBundle); ok {
if !mctx.Config().FlattenApex() || mctx.Config().UnbundledBuild() {
modules := mctx.CreateLocalVariations("", "flattened")
modules[0].(*apexBundle).SetFlattened(false)
modules[1].(*apexBundle).SetFlattened(true)
+ } else {
+ ab.SetFlattened(true)
+ ab.SetFlattenedConfigValue()
}
}
}
@@ -253,11 +310,14 @@
type apexNativeDependencies struct {
// List of native libraries
Native_shared_libs []string
+
// List of native executables
Binaries []string
+
// List of native tests
Tests []string
}
+
type apexMultilibProperties struct {
// Native dependencies whose compile_multilib is "first"
First apexNativeDependencies
@@ -284,8 +344,9 @@
// If unspecified, a default one is automatically generated.
AndroidManifest *string `android:"path"`
- // Canonical name of the APEX bundle in the manifest file.
- // If unspecified, defaults to the value of name
+ // Canonical name of the APEX bundle. Used to determine the path to the activated APEX on
+ // device (/apex/<apex_name>).
+ // If unspecified, defaults to the value of name.
Apex_name *string
// Determines the file contexts file for setting security context to each file in this APEX bundle.
@@ -351,9 +412,19 @@
// List of APKs to package inside APEX
Apps []string
- // To distinguish between flattened and non-flattened variants.
- // if set true, then this variant is flattened variant.
+ // To distinguish between flattened and non-flattened apex.
+ // if set true, then output files are flattened.
Flattened bool `blueprint:"mutated"`
+
+ // if true, it means that TARGET_FLATTEN_APEX is true and
+ // TARGET_BUILD_APPS is false
+ FlattenedConfigValue bool `blueprint:"mutated"`
+
+ // List of SDKs that are used to build this APEX. A reference to an SDK should be either
+ // `name#version` or `name` which is an alias for `name#current`. If left empty, `platform#current`
+ // is implied. This value affects all modules included in this APEX. In other words, they are
+ // also built with the SDKs specified here.
+ Uses_sdks []string
}
type apexTargetBundleProperties struct {
@@ -362,14 +433,17 @@
Android struct {
Multilib apexMultilibProperties
}
+
// Multilib properties only for host.
Host struct {
Multilib apexMultilibProperties
}
+
// Multilib properties only for host linux_bionic.
Linux_bionic struct {
Multilib apexMultilibProperties
}
+
// Multilib properties only for host linux_glibc.
Linux_glibc struct {
Multilib apexMultilibProperties
@@ -377,6 +451,11 @@
}
}
+type apexVndkProperties struct {
+ // Indicates VNDK version of which this VNDK APEX bundles VNDK libs. Default is Platform VNDK Version.
+ Vndk_version *string
+}
+
type apexFileClass int
const (
@@ -472,9 +551,11 @@
type apexBundle struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.SdkBase
properties apexBundleProperties
targetProperties apexTargetBundleProperties
+ vndkProperties apexVndkProperties
apexTypes apexPackaging
@@ -498,12 +579,10 @@
externalDeps []string
testApex bool
+ vndkApex bool
// intermediate path for apex_manifest.json
manifestOut android.WritablePath
-
- // A config value of (TARGET_FLATTEN_APEX && !TARGET_BUILD_APPS)
- flattenedConfigValue bool
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -672,6 +751,16 @@
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+
+ // TODO(jiyong): ensure that all apexes are with non-empty uses_sdks
+ if len(a.properties.Uses_sdks) > 0 {
+ sdkRefs := []android.SdkRef{}
+ for _, str := range a.properties.Uses_sdks {
+ parsed := android.ParseSdkRef(ctx, str, "uses_sdks")
+ sdkRefs = append(sdkRefs, parsed)
+ }
+ a.BuildWithSdks(sdkRefs)
+ }
}
func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
@@ -708,7 +797,7 @@
func (a *apexBundle) getImageVariation(config android.DeviceConfig) string {
if config.VndkVersion() != "" && proptools.Bool(a.properties.Use_vendor) {
- return "vendor"
+ return "vendor." + config.PlatformVndkVersion()
} else {
return "core"
}
@@ -754,6 +843,20 @@
a.properties.Flattened = flattened
}
+func (a *apexBundle) SetFlattenedConfigValue() {
+ a.properties.FlattenedConfigValue = true
+}
+
+// isFlattenedVariant returns true when the current module is the flattened
+// variant of an apex that has both a flattened and an unflattened variant.
+// It returns false when the current module is flattened but there is no
+// unflattened variant, which occurs when ctx.Config().FlattenedApex() returns
+// true. It can be used to avoid collisions between the install paths of the
+// flattened and unflattened variants.
+func (a *apexBundle) isFlattenedVariant() bool {
+ return a.properties.Flattened && !a.properties.FlattenedConfigValue
+}
+
func getCopyManifestForNativeLibrary(ccMod *cc.Module, config android.Config, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) {
// Decide the APEX-local directory by the multilib of the library
// In the future, we may query this to the module.
@@ -1067,6 +1170,8 @@
}
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
+ } else if depTag == android.DefaultsDepTag {
+ return false
} else if am.NoApex() && !android.InList(depName, whitelistNoApex[ctx.ModuleName()]) {
ctx.ModuleErrorf("tries to include no_apex module %s", depName)
}
@@ -1075,10 +1180,6 @@
return false
})
- a.flattenedConfigValue = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
- if a.flattenedConfigValue {
- a.properties.Flattened = true
- }
if a.private_key_file == nil {
ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key))
return
@@ -1086,11 +1187,12 @@
// remove duplicates in filesInfo
removeDup := func(filesInfo []apexFile) []apexFile {
- encountered := make(map[android.Path]bool)
+ encountered := make(map[string]bool)
result := []apexFile{}
for _, f := range filesInfo {
- if !encountered[f.builtFile] {
- encountered[f.builtFile] = true
+ dest := filepath.Join(f.installDir, f.builtFile.Base())
+ if !encountered[dest] {
+ encountered[dest] = true
result = append(result, f)
}
}
@@ -1113,6 +1215,16 @@
}
}
+ // check apex_available requirements
+ for _, fi := range filesInfo {
+ if am, ok := fi.module.(android.ApexModule); ok {
+ if !am.AvailableFor(ctx.ModuleName()) {
+ ctx.ModuleErrorf("requires %q that is not available for the APEX", fi.module.Name())
+ return
+ }
+ }
+ }
+
// prepend the name of this APEX to the module names. These names will be the names of
// modules that will be defined if the APEX is flattened.
for i := range filesInfo {
@@ -1122,18 +1234,28 @@
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = filesInfo
+ // prepare apex_manifest.json
a.manifestOut = android.PathForModuleOut(ctx, "apex_manifest.json")
- // put dependency({provide|require}NativeLibs) in apex_manifest.json
manifestSrc := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
+
+ // put dependency({provide|require}NativeLibs) in apex_manifest.json
provideNativeLibs = android.SortedUniqueStrings(provideNativeLibs)
requireNativeLibs = android.SortedUniqueStrings(android.RemoveListFromList(requireNativeLibs, provideNativeLibs))
+
+ // apex name can be overridden
+ optCommands := []string{}
+ if a.properties.Apex_name != nil {
+ optCommands = append(optCommands, "-v name "+*a.properties.Apex_name)
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: injectApexDependency,
+ Rule: apexManifestRule,
Input: manifestSrc,
Output: a.manifestOut,
Args: map[string]string{
"provideNativeLibs": strings.Join(provideNativeLibs, " "),
"requireNativeLibs": strings.Join(requireNativeLibs, " "),
+ "opt": strings.Join(optCommands, " "),
},
})
@@ -1347,6 +1469,12 @@
optFlags = append(optFlags, "--no_hashtree")
}
+ if a.properties.Apex_name != nil {
+ // If apex_name is set, apexer can skip checking if key name matches with apex name.
+ // Note that apex_manifest is also mended.
+ optFlags = append(optFlags, "--do_not_check_keyname")
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: apexRule,
Implicits: implicitInputs,
@@ -1416,7 +1544,7 @@
})
// Install to $OUT/soong/{target,host}/.../apex
- if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) && !a.properties.Flattened {
+ if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) && !a.isFlattenedVariant() {
ctx.InstallFile(a.installDir, ctx.ModuleName()+suffix, a.outputFiles[apexType])
}
}
@@ -1481,7 +1609,7 @@
}
var suffix string
- if a.properties.Flattened && !a.flattenedConfigValue {
+ if a.isFlattenedVariant() {
suffix = ".flattened"
}
@@ -1492,14 +1620,14 @@
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName+suffix)
- // /apex/<name>/{lib|framework|...}
+ // /apex/<apex_name>/{lib|framework|...}
pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex",
proptools.StringDefault(a.properties.Apex_name, name), fi.installDir)
if a.properties.Flattened && apexType.image() {
// /system/apex/<name>/{lib|framework|...}
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)",
a.installDir.RelPathString(), name, fi.installDir))
- if a.flattenedConfigValue {
+ if !a.isFlattenedVariant() {
fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
}
if len(fi.symlinks) > 0 {
@@ -1581,7 +1709,7 @@
moduleNames = a.androidMkForFiles(w, name, moduleDir, apexType)
}
- if a.properties.Flattened && !a.flattenedConfigValue {
+ if a.isFlattenedVariant() {
name = name + ".flattened"
}
@@ -1596,7 +1724,7 @@
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): .KATI_IMPLICIT_OUTPUTS :=", a.flattenedOutput.String())
- } else {
+ } else if !a.isFlattenedVariant() {
// zip-apex is the less common type so have the name refer to the image-apex
// only and use {name}.zip if you want the zip-apex
if apexType == zipApex && a.apexTypes == both {
@@ -1629,18 +1757,9 @@
}}
}
-func testApexBundleFactory() android.Module {
- return ApexBundleFactory(true /*testApex*/)
-}
-
-func apexBundleFactory() android.Module {
- return ApexBundleFactory(false /*testApex*/)
-}
-
-func ApexBundleFactory(testApex bool) android.Module {
+func newApexBundle() *apexBundle {
module := &apexBundle{
outputFiles: map[apexPackaging]android.WritablePath{},
- testApex: testApex,
}
module.AddProperties(&module.properties)
module.AddProperties(&module.targetProperties)
@@ -1649,9 +1768,43 @@
})
android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
+ android.InitSdkAwareModule(module)
return module
}
+func ApexBundleFactory(testApex bool) android.Module {
+ bundle := newApexBundle()
+ bundle.testApex = testApex
+ return bundle
+}
+
+func testApexBundleFactory() android.Module {
+ bundle := newApexBundle()
+ bundle.testApex = true
+ return bundle
+}
+
+func BundleFactory() android.Module {
+ return newApexBundle()
+}
+
+// apex_vndk creates a special variant of apex modules which contains only VNDK libraries.
+// If `vndk_version` is specified, the VNDK libraries of the specified VNDK version are gathered automatically.
+// If not specified, then the "current" versions are gathered.
+func vndkApexBundleFactory() android.Module {
+ bundle := newApexBundle()
+ bundle.vndkApex = true
+ bundle.AddProperties(&bundle.vndkProperties)
+ android.AddLoadHook(bundle, func(ctx android.LoadHookContext) {
+ ctx.AppendProperties(&struct {
+ Compile_multilib *string
+ }{
+ proptools.StringPtr("both"),
+ })
+ })
+ return bundle
+}
+
//
// Defaults
//
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e2d85ae..ecfa46f 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -40,8 +40,9 @@
return
}
-func testApexError(t *testing.T, pattern, bp string) {
- ctx, config := testApexContext(t, bp)
+func testApexError(t *testing.T, pattern, bp string, handlers ...testCustomizer) {
+ t.Helper()
+ ctx, config := testApexContext(t, bp, handlers...)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs)
@@ -56,8 +57,9 @@
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
}
-func testApex(t *testing.T, bp string) (*android.TestContext, android.Config) {
- ctx, config := testApexContext(t, bp)
+func testApex(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
+ t.Helper()
+ ctx, config := testApexContext(t, bp, handlers...)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
@@ -65,37 +67,54 @@
return ctx, config
}
-func testApexContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
+type testCustomizer func(fs map[string][]byte, config android.Config)
+
+func withFiles(files map[string][]byte) testCustomizer {
+ return func(fs map[string][]byte, config android.Config) {
+ for k, v := range files {
+ fs[k] = v
+ }
+ }
+}
+
+func withTargets(targets map[android.OsType][]android.Target) testCustomizer {
+ return func(fs map[string][]byte, config android.Config) {
+ for k, v := range targets {
+ config.Targets[k] = v
+ }
+ }
+}
+
+func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
config := android.TestArchConfig(buildDir, nil)
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
+ config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")
ctx := android.NewTestArchContext()
- ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apexBundleFactory))
+ ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(BundleFactory))
ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory))
- ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
+ ctx.RegisterModuleType("apex_vndk", android.ModuleFactoryAdaptor(vndkApexBundleFactory))
+ ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(ApexKeyFactory))
ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory))
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_deps", apexDepsMutator)
- ctx.BottomUp("apex", apexMutator)
- ctx.BottomUp("apex_uses", apexUsesMutator)
- ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
- ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
- })
-
+ ctx.RegisterModuleType("cc_defaults", android.ModuleFactoryAdaptor(func() android.Module {
+ return cc.DefaultsFactory()
+ }))
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
+ ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(cc.PrebuiltSharedLibraryFactory))
+ ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(cc.PrebuiltStaticLibraryFactory))
ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(cc.BinaryFactory))
ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
ctx.RegisterModuleType("cc_test", android.ModuleFactoryAdaptor(cc.TestFactory))
ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
+ ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(cc.VndkPrebuiltSharedFactory))
ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
ctx.RegisterModuleType("sh_binary", android.ModuleFactoryAdaptor(android.ShBinaryFactory))
@@ -105,6 +124,7 @@
ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(java.AndroidAppFactory))
+ ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
})
@@ -115,6 +135,15 @@
ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
ctx.BottomUp("version", cc.VersionMutator).Parallel()
ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+ ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator)
+ ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator)
+ })
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_deps", apexDepsMutator)
+ ctx.BottomUp("apex", apexMutator)
+ ctx.BottomUp("apex_uses", apexUsesMutator)
+ ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
+ ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
})
ctx.Register()
@@ -132,6 +161,7 @@
src: "",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
}
toolchain_library {
@@ -146,6 +176,7 @@
src: "",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
}
toolchain_library {
@@ -153,6 +184,7 @@
src: "",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
}
toolchain_library {
@@ -160,6 +192,23 @@
src: "",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-x86_64-android",
+ src: "",
+ vendor_available: true,
+ recovery_available: true,
+ native_bridge_supported: true,
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-i686-android",
+ src: "",
+ vendor_available: true,
+ recovery_available: true,
+ native_bridge_supported: true,
}
cc_object {
@@ -167,6 +216,7 @@
stl: "none",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
}
cc_object {
@@ -174,6 +224,7 @@
stl: "none",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
}
cc_object {
@@ -189,20 +240,23 @@
llndk_library {
name: "libc",
symbol_file: "",
+ native_bridge_supported: true,
}
llndk_library {
name: "libm",
symbol_file: "",
+ native_bridge_supported: true,
}
llndk_library {
name: "libdl",
symbol_file: "",
+ native_bridge_supported: true,
}
`
- ctx.MockFileSystem(map[string][]byte{
+ fs := map[string][]byte{
"Android.bp": []byte(bp),
"build/make/target/product/security": nil,
"apex_manifest.json": nil,
@@ -238,7 +292,13 @@
"frameworks/base/api/current.txt": nil,
"build/make/core/proguard.flags": nil,
"build/make/core/proguard_basic_keeps.flags": nil,
- })
+ }
+
+ for _, handler := range handlers {
+ handler(fs, config)
+ }
+
+ ctx.MockFileSystem(fs)
return ctx, config
}
@@ -711,9 +771,9 @@
// Ensure that runtime_libs dep in included
ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
- injectRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("injectApexDependency")
- ensureListEmpty(t, names(injectRule.Args["provideNativeLibs"]))
- ensureListContains(t, names(injectRule.Args["requireNativeLibs"]), "libfoo.so")
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
+ ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.so")
}
@@ -761,11 +821,11 @@
// Ensure that LLNDK dep is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
- injectRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("injectApexDependency")
- ensureListEmpty(t, names(injectRule.Args["provideNativeLibs"]))
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
// Ensure that LLNDK dep is required
- ensureListContains(t, names(injectRule.Args["requireNativeLibs"]), "libbar.so")
+ ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so")
}
@@ -992,8 +1052,8 @@
inputsString := strings.Join(inputsList, " ")
// ensure that the apex includes vendor variants of the direct and indirect deps
- ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib.so")
- ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib2.so")
+ ensureContains(t, inputsString, "android_arm64_armv8-a_vendor.VER_shared_myapex/mylib.so")
+ ensureContains(t, inputsString, "android_arm64_armv8-a_vendor.VER_shared_myapex/mylib2.so")
// ensure that the apex does not include core variants
ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib.so")
@@ -1210,6 +1270,252 @@
ensureContains(t, cFlags, "-Imy_include")
}
+func TestVndkApexCurrent(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex_vndk {
+ name: "myapex",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libvndk",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libvndksp",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
+ ensureContains(t, copyCmds, "image.apex/lib/libvndksp.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libvndksp.so")
+}
+
+func TestVndkApexWithPrebuilt(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex_vndk {
+ name: "myapex",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_prebuilt_library_shared {
+ name: "libvndkshared",
+ srcs: ["libvndkshared.so"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `, withFiles(map[string][]byte{
+ "libvndkshared.so": nil,
+ }))
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ ensureContains(t, copyCmds, "image.apex/lib/libvndkshared.so")
+}
+
+func TestVndkApexVersion(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex_vndk {
+ name: "myapex_v27",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ vndk_version: "27",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libvndk",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ vndk_prebuilt_shared {
+ name: "libvndk27",
+ version: "27",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ srcs: ["libvndk27.so"],
+ }
+ `, withFiles(map[string][]byte{
+ "libvndk27.so": nil,
+ }))
+
+ apexRule := ctx.ModuleForTests("myapex_v27", "android_common_myapex_v27").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ ensureContains(t, copyCmds, "image.apex/lib/libvndk27.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libvndk27.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib/libvndk.so")
+}
+
+func TestVndkApexErrorWithDuplicateVersion(t *testing.T) {
+ testApexError(t, `module "myapex_v27.*" .*: vndk_version: 27 is already defined in "myapex_v27.*"`, `
+ apex_vndk {
+ name: "myapex_v27",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ vndk_version: "27",
+ }
+ apex_vndk {
+ name: "myapex_v27_other",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ vndk_version: "27",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libvndk",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ vndk_prebuilt_shared {
+ name: "libvndk",
+ version: "27",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ srcs: ["libvndk.so"],
+ }
+ `, withFiles(map[string][]byte{
+ "libvndk.so": nil,
+ }))
+}
+
+func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex_vndk {
+ name: "myapex",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libvndk",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ native_bridge_supported: true,
+ host_supported: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `, withTargets(map[android.OsType][]android.Target{
+ android.Android: []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm64", NativeBridgeRelativePath: "x86_64"},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm", NativeBridgeRelativePath: "x86"},
+ },
+ }))
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
+
+ // apex
+ ensureNotContains(t, copyCmds, "image.apex/lib/x86/libvndk.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/x86_64/libvndk.so")
+}
+
+func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
+ testApexError(t, `module "myapex" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
+ apex_vndk {
+ name: "myapex",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ native_bridge_supported: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libvndk",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ native_bridge_supported: true,
+ host_supported: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+}
+
func TestDependenciesInApexManifest(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -1276,34 +1582,56 @@
}
`)
- var injectRule android.TestingBuildParams
+ var apexManifestRule android.TestingBuildParams
var provideNativeLibs, requireNativeLibs []string
- injectRule = ctx.ModuleForTests("myapex_nodep", "android_common_myapex_nodep").Rule("injectApexDependency")
- provideNativeLibs = names(injectRule.Args["provideNativeLibs"])
- requireNativeLibs = names(injectRule.Args["requireNativeLibs"])
+ apexManifestRule = ctx.ModuleForTests("myapex_nodep", "android_common_myapex_nodep").Rule("apexManifestRule")
+ provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
+ requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListEmpty(t, provideNativeLibs)
ensureListEmpty(t, requireNativeLibs)
- injectRule = ctx.ModuleForTests("myapex_dep", "android_common_myapex_dep").Rule("injectApexDependency")
- provideNativeLibs = names(injectRule.Args["provideNativeLibs"])
- requireNativeLibs = names(injectRule.Args["requireNativeLibs"])
+ apexManifestRule = ctx.ModuleForTests("myapex_dep", "android_common_myapex_dep").Rule("apexManifestRule")
+ provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
+ requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListEmpty(t, provideNativeLibs)
ensureListContains(t, requireNativeLibs, "libfoo.so")
- injectRule = ctx.ModuleForTests("myapex_provider", "android_common_myapex_provider").Rule("injectApexDependency")
- provideNativeLibs = names(injectRule.Args["provideNativeLibs"])
- requireNativeLibs = names(injectRule.Args["requireNativeLibs"])
+ apexManifestRule = ctx.ModuleForTests("myapex_provider", "android_common_myapex_provider").Rule("apexManifestRule")
+ provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
+ requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListContains(t, provideNativeLibs, "libfoo.so")
ensureListEmpty(t, requireNativeLibs)
- injectRule = ctx.ModuleForTests("myapex_selfcontained", "android_common_myapex_selfcontained").Rule("injectApexDependency")
- provideNativeLibs = names(injectRule.Args["provideNativeLibs"])
- requireNativeLibs = names(injectRule.Args["requireNativeLibs"])
+ apexManifestRule = ctx.ModuleForTests("myapex_selfcontained", "android_common_myapex_selfcontained").Rule("apexManifestRule")
+ provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
+ requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListContains(t, provideNativeLibs, "libfoo.so")
ensureListEmpty(t, requireNativeLibs)
}
+func TestApexName(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apex_name: "com.android.myapex",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+
+ module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ apexManifestRule := module.Rule("apexManifestRule")
+ ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
+ apexRule := module.Rule("apexRule")
+ ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
+}
+
func TestNonTestApex(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -1824,6 +2152,7 @@
}
func TestApexUsesFailsIfUseNoApex(t *testing.T) {
+ // 'no_apex' prevents a module to be included in an apex
testApexError(t, `tries to include no_apex module mylib2`, `
apex {
name: "commonapex",
@@ -1854,6 +2183,7 @@
}
`)
+ // respect 'no_apex' even with static link
testApexError(t, `tries to include no_apex module mylib2`, `
apex {
name: "commonapex",
@@ -1884,6 +2214,86 @@
}
`)
+ // 'no_apex' can be applied via defaults
+ testApexError(t, `tries to include no_apex module mylib2`, `
+ apex {
+ name: "commonapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ static_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_defaults {
+ name: "mylib2_defaults",
+ system_shared_libs: [],
+ stl: "none",
+ no_apex: true,
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ defaults: ["mylib2_defaults"],
+ }
+ `)
+}
+
+func TestNoApexWorksWithWhitelist(t *testing.T) {
+
+ testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_defaults {
+ name: "mylib2_defaults",
+ system_shared_libs: [],
+ stl: "none",
+ no_apex: true,
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ defaults: ["mylib2_defaults"],
+ }
+ `, func(fs map[string][]byte, config android.Config) {
+ whitelistNoApex = map[string][]string{
+ "myapex": []string{"mylib2"},
+ }
+ })
+}
+
+func TestNoApexCanBeDependedOnViaStubs(t *testing.T) {
ctx, _ := testApex(t, `
apex {
name: "myapex",
@@ -1916,6 +2326,7 @@
},
}
+ // this won't be included in "myapex", so 'no_apex' is still valid in this case.
cc_library {
name: "mylib3",
srcs: ["mylib.cpp"],
@@ -1932,7 +2343,6 @@
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib3.so")
-
}
func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
@@ -2012,6 +2422,158 @@
}
+func TestApexAvailable(t *testing.T) {
+ // libfoo is not available to myapex, but only to otherapex
+ testApexError(t, "requires \"libfoo\" that is not available for the APEX", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["otherapex"],
+ }`)
+
+ // libbar is an indirect dep
+ testApexError(t, "requires \"libbar\" that is not available for the APEX", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ shared_libs: ["libbar"],
+ system_shared_libs: [],
+ apex_available: ["myapex", "otherapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["otherapex"],
+ }`)
+
+ testApexError(t, "\"otherapex\" is not a valid module name", `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["otherapex"],
+ }`)
+
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo", "libbar"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["//apex_available:anyapex"],
+ }`)
+
+ // check that libfoo and libbar are created only for myapex, but not for the platform
+ ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
+ ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_core_shared")
+
+ ctx, _ = testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["//apex_available:platform"],
+ }`)
+
+ // check that libfoo is created only for the platform
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/apex/key.go b/apex/key.go
index 08cd45e..ffde315 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -27,7 +27,7 @@
var String = proptools.String
func init() {
- android.RegisterModuleType("apex_key", apexKeyFactory)
+ android.RegisterModuleType("apex_key", ApexKeyFactory)
android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
}
@@ -53,7 +53,7 @@
Installable *bool
}
-func apexKeyFactory() android.Module {
+func ApexKeyFactory() android.Module {
module := &apexKey{}
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.HostAndDeviceDefault, android.MultilibCommon)
diff --git a/build_kzip.bash b/build_kzip.bash
index 5364e7f..1e0d48f 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -1,25 +1,27 @@
-# /bin/bash -uv
+#! /bin/bash -uv
#
# Build kzip files (source files for the indexing pipeline) for the given configuration,
# merge them and place the resulting all.kzip into $DIST_DIR.
# It is assumed that the current directory is the top of the source tree.
-# The following enviromnet variables affect the result:
-# TARGET_PRODUCT target device name, e.g., `aosp_blueline`
-# TARGET_BUILD_VARIANT variant, e.g., `userdebug`
-# OUT_DIR where the build is happening (./out if not specified)
+# The following environment variables affect the result:
+# BUILD_NUMBER build number, used to generate unique ID (will use UUID if not set)
# DIST_DIR where the resulting all.kzip will be placed
-# XREF_CORPUS source code repository URI, e.g.,
-# `android.googlesource.com/platform/superproject`
+# OUT_DIR output directory (out if not specified})
+# TARGET_BUILD_VARIANT variant, e.g., `userdebug`
+# TARGET_PRODUCT target device name, e.g., 'aosp_blueline'
+# XREF_CORPUS source code repository URI, e.g., 'android.googlesource.com/platform/superproject'
-# The extraction might fail for some source files, so run with -k
+: ${BUILD_NUMBER:=$(uuidgen)}
+
+# The extraction might fail for some source files, so run with -k and then check that
+# sufficiently many files were generated.
build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
-
-# We build with -k, so check that we have generated at least 100K files
-# (the actual number is 180K+)
-declare -r kzip_count=$(find $OUT_DIR -name '*.kzip' | wc -l)
+declare -r out="${OUT_DIR:-out}"
+declare -r kzip_count=$(find "$out" -name '*.kzip' | wc -l)
(($kzip_count>100000)) || { printf "Too few kzip files were generated: %d\n" $kzip_count; exit 1; }
# Pack
# TODO(asmundak): this should be done by soong.
-declare -r allkzip=all.kzip
-"${OUT_DIR:-out}/soong/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find $OUT_DIR -name '*.kzip')
+declare -r allkzip="$BUILD_NUMBER.kzip"
+"$out/soong/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find "$out" -name '*.kzip')
+
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 66dd838..aab4edd 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -37,6 +37,7 @@
Os() android.OsType
Host() bool
useVndk() bool
+ vndkVersion() string
static() bool
inRecovery() bool
}
@@ -109,17 +110,7 @@
}
c.subAndroidMk(&ret, c.installer)
- if c.Target().NativeBridge == android.NativeBridgeEnabled {
- ret.SubName += nativeBridgeSuffix
- }
-
- if c.useVndk() && c.hasVendorVariant() {
- // .vendor suffix is added only when we will have two variants: core and vendor.
- // The suffix is not added for vendor-only module.
- ret.SubName += vendorSuffix
- } else if c.inRecovery() && !c.onlyInRecovery() {
- ret.SubName += recoverySuffix
- }
+ ret.SubName += c.Properties.SubName
return ret
}
@@ -312,6 +303,33 @@
androidMkWriteTestData(test.data, ctx, ret)
}
+func (fuzz *fuzzBinary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+ ctx.subAndroidMk(ret, fuzz.binaryDecorator)
+
+ var fuzzFiles []string
+ for _, d := range fuzz.corpus {
+ rel := d.Rel()
+ path := d.String()
+ path = strings.TrimSuffix(path, rel)
+ fuzzFiles = append(fuzzFiles, path+":corpus/"+d.Base())
+ }
+
+ if fuzz.dictionary != nil {
+ path := strings.TrimSuffix(fuzz.dictionary.String(), fuzz.dictionary.Rel())
+ fuzzFiles = append(fuzzFiles, path+":"+fuzz.dictionary.Base())
+ }
+
+ if len(fuzzFiles) > 0 {
+ ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+ fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(fuzzFiles, " "))
+ })
+ }
+
+ ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+ fmt.Fprintln(w, "LOCAL_IS_FUZZ_TARGET := true")
+ })
+}
+
func (test *testLibrary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
ctx.subAndroidMk(ret, test.libraryDecorator)
}
@@ -357,7 +375,6 @@
func (c *llndkStubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
ret.Class = "SHARED_LIBRARIES"
- ret.SubName = vendorSuffix
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
c.libraryDecorator.androidMkWriteExportedFlags(w)
diff --git a/cc/builder.go b/cc/builder.go
index 42d809a..c4f65da 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -224,12 +224,13 @@
_ = pctx.SourcePathVariable("cxxExtractor",
"prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/cxx_extractor")
+ _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
_ = pctx.VariableFunc("kytheCorpus",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
kytheExtract = pctx.StaticRule("kythe",
blueprint.RuleParams{
- Command: "rm -f $out && KYTHE_CORPUS=${kytheCorpus} KYTHE_OUTPUT_FILE=$out $cxxExtractor $cFlags $in ",
- CommandDeps: []string{"$cxxExtractor"},
+ Command: "rm -f $out && KYTHE_CORPUS=${kytheCorpus} KYTHE_OUTPUT_FILE=$out KYTHE_VNAMES=$kytheVnames $cxxExtractor $cFlags $in ",
+ CommandDeps: []string{"$cxxExtractor", "$kytheVnames"},
},
"cFlags")
)
@@ -764,7 +765,7 @@
// Generate a rule for compiling multiple .o files to a .o using ld partial linking
func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
- flags builderFlags, outputFile android.WritablePath) {
+ flags builderFlags, outputFile android.WritablePath, deps android.Paths) {
ldCmd := "${config.ClangBin}/clang++"
@@ -773,6 +774,7 @@
Description: "link " + outputFile.Base(),
Output: outputFile,
Inputs: objFiles,
+ Implicits: deps,
Args: map[string]string{
"ldCmd": ldCmd,
"ldFlags": flags.ldFlags,
diff --git a/cc/cc.go b/cc/cc.go
index 1826f52..0f2cb4c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -36,9 +36,9 @@
android.RegisterModuleType("cc_defaults", defaultsFactory)
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("vndk", VndkMutator).Parallel()
ctx.BottomUp("image", ImageMutator).Parallel()
ctx.BottomUp("link", LinkageMutator).Parallel()
- ctx.BottomUp("vndk", VndkMutator).Parallel()
ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
ctx.BottomUp("version", VersionMutator).Parallel()
@@ -200,7 +200,8 @@
PreventInstall bool `blueprint:"mutated"`
ApexesProvidingSharedLibs []string `blueprint:"mutated"`
- UseVndk bool `blueprint:"mutated"`
+ VndkVersion string `blueprint:"mutated"`
+ SubName string `blueprint:"mutated"`
// *.logtags files, to combine together in order to generate the /system/etc/event-log-tags
// file
@@ -400,6 +401,14 @@
return staticDepTag
}
+func CrtBeginDepTag() dependencyTag {
+ return crtBeginDepTag
+}
+
+func CrtEndDepTag() dependencyTag {
+ return crtEndDepTag
+}
+
// Module contains the properties and members used by all C/C++ module types, and implements
// the blueprint.Module interface. It delegates to compiler, linker, and installer interfaces
// to construct the output file. Behavior can be customized with a Customizer interface
@@ -407,6 +416,7 @@
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
+ android.SdkBase
Properties BaseProperties
VendorProperties VendorProperties
@@ -478,6 +488,19 @@
return ""
}
+// IsVndkOnSystem returns true if a module is supposed to be a vndk library provided by system to vendor
+func (c *Module) IsVndkOnSystem() bool {
+ if linker, ok := c.linker.(libraryInterface); ok {
+ return linker.shared() && c.isVndk() && c.useVndk() && !c.isVndkExt()
+ }
+
+ return false
+}
+
+func (c *Module) VndkVersion() string {
+ return c.vndkVersion()
+}
+
func (c *Module) Init() android.Module {
c.AddProperties(&c.Properties, &c.VendorProperties)
if c.compiler != nil {
@@ -529,10 +552,9 @@
}
})
android.InitAndroidArchModule(c, c.hod, c.multilib)
-
- android.InitDefaultableModule(c)
-
android.InitApexModule(c)
+ android.InitDefaultableModule(c)
+ android.InitSdkAwareModule(c)
return c
}
@@ -549,7 +571,7 @@
}
func (c *Module) useVndk() bool {
- return c.Properties.UseVndk
+ return c.Properties.VndkVersion != ""
}
func (c *Module) isCoverageVariant() bool {
@@ -583,10 +605,7 @@
}
func (c *Module) vndkVersion() string {
- if vndkdep := c.vndkdep; vndkdep != nil {
- return vndkdep.Properties.Vndk.Version
- }
- return ""
+ return c.Properties.VndkVersion
}
func (c *Module) isPgoCompile() bool {
@@ -996,6 +1015,31 @@
c.makeLinkType = c.getMakeLinkType(actx)
+ c.Properties.SubName = ""
+
+ if c.Target().NativeBridge == android.NativeBridgeEnabled {
+ c.Properties.SubName += nativeBridgeSuffix
+ }
+
+ if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ // .vendor suffix is added for backward compatibility with VNDK snapshot whose names with
+ // such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
+ c.Properties.SubName += vendorSuffix
+ } else if _, ok := c.linker.(*llndkStubDecorator); ok || (c.useVndk() && c.hasVendorVariant()) {
+ // .vendor.{version} suffix is added only when we will have two variants: core and vendor.
+ // The suffix is not added for vendor-only module.
+ c.Properties.SubName += vendorSuffix
+ vendorVersion := actx.DeviceConfig().VndkVersion()
+ if vendorVersion == "current" {
+ vendorVersion = actx.DeviceConfig().PlatformVndkVersion()
+ }
+ if c.Properties.VndkVersion != vendorVersion {
+ c.Properties.SubName += "." + c.Properties.VndkVersion
+ }
+ } else if c.inRecovery() && !c.onlyInRecovery() {
+ c.Properties.SubName += recoverySuffix
+ }
+
ctx := &moduleContext{
ModuleContext: actx,
moduleContextImpl: moduleContextImpl{
@@ -1483,9 +1527,11 @@
if vndkdep := c.vndkdep; vndkdep != nil {
if vndkdep.isVndkExt() {
- baseModuleMode := vendorMode
+ var baseModuleMode string
if actx.DeviceConfig().VndkVersion() == "" {
baseModuleMode = coreMode
+ } else {
+ baseModuleMode = c.imageVariation()
}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "image", Variation: baseModuleMode},
@@ -1508,7 +1554,7 @@
// Host code is not restricted
return
}
- if from.Properties.UseVndk {
+ if from.useVndk() {
// Though vendor code is limited by the vendor mutator,
// each vendor-available module needs to check
// link-type for VNDK.
@@ -1915,7 +1961,15 @@
} else if c.useVndk() && bothVendorAndCoreVariantsExist {
// The vendor module in Make will have been renamed to not conflict with the core
// module, so update the dependency name here accordingly.
- return libName + vendorSuffix
+ ret := libName + vendorSuffix
+ vendorVersion := ctx.DeviceConfig().VndkVersion()
+ if vendorVersion == "current" {
+ vendorVersion = ctx.DeviceConfig().PlatformVndkVersion()
+ }
+ if c.Properties.VndkVersion != vendorVersion {
+ ret += "." + c.Properties.VndkVersion
+ }
+ return ret
} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
return libName + vendorPublicLibrarySuffix
} else if ccDep.inRecovery() && !ccDep.onlyInRecovery() {
@@ -2101,13 +2155,12 @@
}
func (c *Module) imageVariation() string {
- variation := "core"
if c.useVndk() {
- variation = "vendor"
+ return vendorMode + "." + c.Properties.VndkVersion
} else if c.inRecovery() {
- variation = "recovery"
+ return recoveryMode
}
- return variation
+ return coreMode
}
func (c *Module) IDEInfo(dpInfo *android.IdeInfo) {
@@ -2155,10 +2208,13 @@
&BaseLinkerProperties{},
&ObjectLinkerProperties{},
&LibraryProperties{},
+ &StaticProperties{},
+ &SharedProperties{},
&FlagExporterProperties{},
&BinaryLinkerProperties{},
&TestProperties{},
&TestBinaryProperties{},
+ &FuzzProperties{},
&StlProperties{},
&SanitizeProperties{},
&StripProperties{},
@@ -2173,8 +2229,8 @@
&android.ProtoProperties{},
)
- android.InitDefaultsModule(module)
android.InitApexModule(module)
+ android.InitDefaultsModule(module)
return module
}
@@ -2184,7 +2240,7 @@
// SDK libraries. (which framework-private libraries can use)
coreMode = "core"
- // vendorMode is the variant used for /vendor code that compiles
+ // vendorMode is the variant prefix used for /vendor code that compiles
// against the VNDK.
vendorMode = "vendor"
@@ -2248,7 +2304,10 @@
variants = append(variants, coreMode)
}
if vendorVariantNeeded {
- variants = append(variants, vendorMode)
+ variants = append(variants, vendorMode+"."+mctx.DeviceConfig().PlatformVndkVersion())
+ if vndkVersion := mctx.DeviceConfig().VndkVersion(); vndkVersion != "current" {
+ variants = append(variants, vendorMode+"."+vndkVersion)
+ }
}
if recoveryVariantNeeded {
variants = append(variants, recoveryMode)
@@ -2320,9 +2379,16 @@
}
var coreVariantNeeded bool = false
- var vendorVariantNeeded bool = false
var recoveryVariantNeeded bool = false
+ var vendorVariants []string
+
+ platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
+ deviceVndkVersion := mctx.DeviceConfig().VndkVersion()
+ if deviceVndkVersion == "current" {
+ deviceVndkVersion = platformVndkVersion
+ }
+
if mctx.DeviceConfig().VndkVersion() == "" {
// If the device isn't compiling against the VNDK, we always
// use the core mode.
@@ -2333,22 +2399,31 @@
} else if _, ok := m.linker.(*llndkStubDecorator); ok {
// LL-NDK stubs only exist in the vendor variant, since the
// real libraries will be used in the core variant.
- vendorVariantNeeded = true
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ deviceVndkVersion,
+ )
} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
// ... and LL-NDK headers as well
- vendorVariantNeeded = true
- } else if _, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ deviceVndkVersion,
+ )
+ } else if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
// PRODUCT_EXTRA_VNDK_VERSIONS.
- vendorVariantNeeded = true
+ vendorVariants = append(vendorVariants, lib.version())
} else if m.hasVendorVariant() && !vendorSpecific {
// This will be available in both /system and /vendor
// or a /system directory that is available to vendor.
coreVariantNeeded = true
- vendorVariantNeeded = true
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ if m.isVndk() {
+ vendorVariants = append(vendorVariants, deviceVndkVersion)
+ }
} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
// This will be available in /vendor (or /odm) only
- vendorVariantNeeded = true
+ vendorVariants = append(vendorVariants, deviceVndkVersion)
} else {
// This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK
@@ -2377,17 +2452,17 @@
if coreVariantNeeded {
variants = append(variants, coreMode)
}
- if vendorVariantNeeded {
- variants = append(variants, vendorMode)
+ for _, variant := range android.FirstUniqueStrings(vendorVariants) {
+ variants = append(variants, vendorMode+"."+variant)
}
if recoveryVariantNeeded {
variants = append(variants, recoveryMode)
}
mod := mctx.CreateVariations(variants...)
for i, v := range variants {
- if v == vendorMode {
+ if strings.HasPrefix(v, vendorMode+".") {
m := mod[i].(*Module)
- m.Properties.UseVndk = true
+ m.Properties.VndkVersion = strings.TrimPrefix(v, vendorMode+".")
squashVendorSrcs(m)
} else if v == recoveryMode {
m := mod[i].(*Module)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index c9eb421..689aacd 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -15,8 +15,6 @@
package cc
import (
- "android/soong/android"
-
"fmt"
"io/ioutil"
"os"
@@ -25,6 +23,8 @@
"sort"
"strings"
"testing"
+
+ "android/soong/android"
)
var buildDir string
@@ -53,6 +53,7 @@
}
func testCcWithConfig(t *testing.T, bp string, config android.Config) *android.TestContext {
+ t.Helper()
return testCcWithConfigForOs(t, bp, config, android.Android)
}
@@ -112,7 +113,7 @@
const (
coreVariant = "android_arm64_armv8-a_core_shared"
- vendorVariant = "android_arm64_armv8-a_vendor_shared"
+ vendorVariant = "android_arm64_armv8-a_vendor.VER_shared"
recoveryVariant = "android_arm64_armv8-a_recovery_shared"
)
@@ -328,8 +329,8 @@
vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
- variant := "android_arm64_armv8-a_vendor_shared"
- variant2nd := "android_arm_armv7-a-neon_vendor_shared"
+ variant := "android_arm64_armv8-a_vendor.VER_shared"
+ variant2nd := "android_arm_armv7-a-neon_vendor.VER_shared"
checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLibPath, variant)
checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLib2ndPath, variant2nd)
@@ -1343,6 +1344,8 @@
assertArrayString(t, *vndkPrivateLibraries(config),
[]string{"libllndkprivate", "libvndkprivate"})
+ vendorVariant27 := "android_arm64_armv8-a_vendor.27_shared"
+
tests := []struct {
variant string
name string
@@ -1353,8 +1356,8 @@
{vendorVariant, "libvndkprivate", "native:vndk_private"},
{vendorVariant, "libvendor", "native:vendor"},
{vendorVariant, "libvndkext", "native:vendor"},
- {vendorVariant, "prevndk.vndk.27.arm.binder32", "native:vndk"},
{vendorVariant, "libllndk.llndk", "native:vndk"},
+ {vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"},
{coreVariant, "libvndk", "native:platform"},
{coreVariant, "libvndkprivate", "native:platform"},
{coreVariant, "libllndk", "native:platform"},
@@ -1792,7 +1795,7 @@
`)
// _static variant is used since _shared reuses *.o from the static variant
- cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor_static").Rule("cc")
+ cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor.VER_static").Rule("cc")
cflags := cc.Args["cFlags"]
if !strings.Contains(cflags, "-Imy_include") {
t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
@@ -1878,7 +1881,7 @@
// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
// and vendor variants.
- variant = "android_arm64_armv8-a_vendor_shared"
+ variant = "android_arm64_armv8-a_vendor.VER_shared"
module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"libvendor_available1.vendor"}, module)
@@ -1894,7 +1897,7 @@
module := ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
- variant = "android_arm64_armv8-a_vendor_shared"
+ variant = "android_arm64_armv8-a_vendor.VER_shared"
module = ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
checkRuntimeLibs(t, nil, module)
}
@@ -2091,9 +2094,9 @@
}
// test if libvendor is linked to the real shared lib
- ld = ctx.ModuleForTests("libvendor", strings.Replace(variant, "_core", "_vendor", 1)).Rule("ld")
+ ld = ctx.ModuleForTests("libvendor", strings.Replace(variant, "_core", "_vendor.VER", 1)).Rule("ld")
libflags = ld.Args["libFlags"]
- stubPaths = getOutputPaths(ctx, strings.Replace(variant, "_core", "_vendor", 1), []string{"libvendorpublic"})
+ stubPaths = getOutputPaths(ctx, strings.Replace(variant, "_core", "_vendor.VER", 1), []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libvendor must contain %#v, but was %#v", stubPaths[0], libflags)
}
@@ -2319,3 +2322,67 @@
}
}
}
+
+func TestDefaults(t *testing.T) {
+ ctx := testCc(t, `
+ cc_defaults {
+ name: "defaults",
+ srcs: ["foo.c"],
+ static: {
+ srcs: ["bar.c"],
+ },
+ shared: {
+ srcs: ["baz.c"],
+ },
+ }
+
+ cc_library_static {
+ name: "libstatic",
+ defaults: ["defaults"],
+ }
+
+ cc_library_shared {
+ name: "libshared",
+ defaults: ["defaults"],
+ }
+
+ cc_library {
+ name: "libboth",
+ defaults: ["defaults"],
+ }
+
+ cc_binary {
+ name: "binary",
+ defaults: ["defaults"],
+ }`)
+
+ pathsToBase := func(paths android.Paths) []string {
+ var ret []string
+ for _, p := range paths {
+ ret = append(ret, p.Base())
+ }
+ return ret
+ }
+
+ shared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_core_shared").Rule("ld")
+ if g, w := pathsToBase(shared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("libshared ld rule wanted %q, got %q", w, g)
+ }
+ bothShared := ctx.ModuleForTests("libboth", "android_arm64_armv8-a_core_shared").Rule("ld")
+ if g, w := pathsToBase(bothShared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("libboth ld rule wanted %q, got %q", w, g)
+ }
+ binary := ctx.ModuleForTests("binary", "android_arm64_armv8-a_core").Rule("ld")
+ if g, w := pathsToBase(binary.Inputs), []string{"foo.o"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("binary ld rule wanted %q, got %q", w, g)
+ }
+
+ static := ctx.ModuleForTests("libstatic", "android_arm64_armv8-a_core_static").Rule("ar")
+ if g, w := pathsToBase(static.Inputs), []string{"foo.o", "bar.o"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("libstatic ar rule wanted %q, got %q", w, g)
+ }
+ bothStatic := ctx.ModuleForTests("libboth", "android_arm64_armv8-a_core_static").Rule("ar")
+ if g, w := pathsToBase(bothStatic.Inputs), []string{"foo.o", "bar.o"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("libboth ar rule wanted %q, got %q", w, g)
+ }
+}
diff --git a/cc/cflag_artifacts.go b/cc/cflag_artifacts.go
new file mode 100644
index 0000000..9ed3876
--- /dev/null
+++ b/cc/cflag_artifacts.go
@@ -0,0 +1,188 @@
+package cc
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterSingletonType("cflag_artifacts_text", cflagArtifactsTextFactory)
+}
+
+var (
+ TrackedCFlags = []string{
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wthread-safety",
+ "-O3",
+ }
+
+ TrackedCFlagsDir = []string{
+ "device/google/",
+ "vendor/google/",
+ }
+)
+
+const FileBP = 50
+
+// Stores output files.
+type cflagArtifactsText struct {
+ interOutputs map[string]android.WritablePaths
+ outputs android.WritablePaths
+}
+
+// allowedDir verifies if the directory/project is part of the TrackedCFlagsDir
+// filter.
+func allowedDir(subdir string) bool {
+ subdir += "/"
+ for _, prefix := range TrackedCFlagsDir {
+ if strings.HasPrefix(subdir, prefix) {
+ return true
+ }
+ }
+ return false
+}
+
+func (s *cflagArtifactsText) genFlagFilename(flag string) string {
+ return fmt.Sprintf("module_cflags%s.txt", flag)
+}
+
+// incrementFile is used to generate an output path object with the passed in flag
+// and part number.
+// e.g. FLAG + part # -> out/soong/cflags/module_cflags-FLAG.txt.0
+func (s *cflagArtifactsText) incrementFile(ctx android.SingletonContext,
+ flag string, part int) (string, android.OutputPath) {
+
+ filename := fmt.Sprintf("%s.%d", s.genFlagFilename(flag), part)
+ filepath := android.PathForOutput(ctx, "cflags", filename)
+ s.interOutputs[flag] = append(s.interOutputs[flag], filepath)
+ return filename, filepath
+}
+
+// GenCFlagArtifactParts is used to generate the build rules which produce the
+// intermediary files for each desired C Flag artifact
+// e.g. module_cflags-FLAG.txt.0, module_cflags-FLAG.txt.1, ...
+func (s *cflagArtifactsText) GenCFlagArtifactParts(ctx android.SingletonContext,
+ flag string, using bool, modules []string, part int) int {
+
+ cleanedName := strings.Replace(flag, "=", "_", -1)
+ filename, filepath := s.incrementFile(ctx, cleanedName, part)
+ rule := android.NewRuleBuilder()
+ rule.Command().Textf("rm -f %s", filepath.String())
+
+ if using {
+ rule.Command().
+ Textf("echo '# Modules using %s'", flag).
+ FlagWithOutput(">> ", filepath)
+ } else {
+ rule.Command().
+ Textf("echo '# Modules not using %s'", flag).
+ FlagWithOutput(">> ", filepath)
+ }
+
+ length := len(modules)
+
+ if length == 0 {
+ rule.Build(pctx, ctx, filename, "gen "+filename)
+ part++
+ }
+
+ // Following loop splits the module list for each tracked C Flag into
+ // chunks of length FileBP (file breakpoint) and generates a partial artifact
+ // (intermediary file) build rule for each split.
+ moduleShards := android.ShardStrings(modules, FileBP)
+ for index, shard := range moduleShards {
+ rule.Command().
+ Textf("for m in %s; do echo $m",
+ strings.Join(proptools.ShellEscapeList(shard), " ")).
+ FlagWithOutput(">> ", filepath).
+ Text("; done")
+ rule.Build(pctx, ctx, filename, "gen "+filename)
+
+ if index+1 != len(moduleShards) {
+ filename, filepath = s.incrementFile(ctx, cleanedName, part+index+1)
+ rule = android.NewRuleBuilder()
+ rule.Command().Textf("rm -f %s", filepath.String())
+ }
+ }
+
+ return part + len(moduleShards)
+}
+
+// GenCFlagArtifacts is used to generate build rules which combine the
+// intermediary files of a specific tracked flag into a single C Flag artifact
+// for each tracked flag.
+// e.g. module_cflags-FLAG.txt.0 + module_cflags-FLAG.txt.1 = module_cflags-FLAG.txt
+func (s *cflagArtifactsText) GenCFlagArtifacts(ctx android.SingletonContext) {
+ // Scans through s.interOutputs and creates a build rule for each tracked C
+ // Flag that concatenates the associated intermediary file into a single
+ // artifact.
+ for _, flag := range TrackedCFlags {
+ // Generate build rule to combine related intermediary files into a
+ // C Flag artifact
+ rule := android.NewRuleBuilder()
+ filename := s.genFlagFilename(flag)
+ outputpath := android.PathForOutput(ctx, "cflags", filename)
+ rule.Command().
+ Text("cat").
+ Inputs(s.interOutputs[flag].Paths()).
+ FlagWithOutput("> ", outputpath)
+ rule.Build(pctx, ctx, filename, "gen "+filename)
+ s.outputs = append(s.outputs, outputpath)
+ }
+}
+
+func (s *cflagArtifactsText) GenerateBuildActions(ctx android.SingletonContext) {
+ modulesWithCFlag := make(map[string][]string)
+
+ // Scan through all modules, selecting the ones that are part of the filter,
+ // and then storing into a map which tracks whether or not tracked C flag is
+ // used or not.
+ ctx.VisitAllModules(func(module android.Module) {
+ if ccModule, ok := module.(*Module); ok {
+ if allowedDir(ctx.ModuleDir(ccModule)) {
+ cflags := ccModule.flags.CFlags
+ cppflags := ccModule.flags.CppFlags
+ module := fmt.Sprintf("%s:%s (%s)",
+ ctx.BlueprintFile(ccModule),
+ ctx.ModuleName(ccModule),
+ ctx.ModuleSubDir(ccModule))
+ for _, flag := range TrackedCFlags {
+ if inList(flag, cflags) || inList(flag, cppflags) {
+ modulesWithCFlag[flag] = append(modulesWithCFlag[flag], module)
+ } else {
+ modulesWithCFlag["!"+flag] = append(modulesWithCFlag["!"+flag], module)
+ }
+ }
+ }
+ }
+ })
+
+ // Traversing map and setting up rules to produce intermediary files which
+ // contain parts of each expected C Flag artifact.
+ for _, flag := range TrackedCFlags {
+ sort.Strings(modulesWithCFlag[flag])
+ part := s.GenCFlagArtifactParts(ctx, flag, true, modulesWithCFlag[flag], 0)
+ sort.Strings(modulesWithCFlag["!"+flag])
+ s.GenCFlagArtifactParts(ctx, flag, false, modulesWithCFlag["!"+flag], part)
+ }
+
+ // Combine intermediary files into a single C Flag artifact.
+ s.GenCFlagArtifacts(ctx)
+}
+
+func cflagArtifactsTextFactory() android.Singleton {
+ return &cflagArtifactsText{
+ interOutputs: make(map[string]android.WritablePaths),
+ }
+}
+
+func (s *cflagArtifactsText) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict("SOONG_MODULES_CFLAG_ARTIFACTS", strings.Join(s.outputs.Strings(), " "))
+}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 3636ae9..71bea42 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -115,10 +115,6 @@
// TODO: can we remove this now?
"-Wno-reserved-id-macro",
- // Disable overly aggressive warning for format strings.
- // Bug: 20148343
- "-Wno-format-pedantic",
-
// Workaround for ccache with clang.
// See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html.
"-Wno-unused-command-line-argument",
@@ -167,10 +163,6 @@
// new warnings are fixed.
"-Wno-tautological-constant-compare",
"-Wno-tautological-type-limit-compare",
-
- // Disable c++98-specific warning since Android is not concerned with C++98
- // compatibility.
- "-Wno-c++98-compat-extra-semi",
}, " "))
// Extra cflags for projects under external/ directory to disable warnings that are infeasible
diff --git a/cc/config/global.go b/cc/config/global.go
index d873494..0943126 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -108,6 +108,7 @@
noOverrideGlobalCflags = []string{
"-Werror=int-to-pointer-cast",
"-Werror=pointer-to-int-cast",
+ "-Werror=fortify-source",
}
IllegalFlags = []string{
@@ -123,8 +124,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r365631"
- ClangDefaultShortVersion = "9.0.6"
+ ClangDefaultVersion = "clang-r365631b"
+ ClangDefaultShortVersion = "9.0.7"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/fuzz.go b/cc/fuzz.go
index b0fb262..c19fdc5 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "strings"
"github.com/google/blueprint/proptools"
@@ -23,8 +24,17 @@
"android/soong/cc/config"
)
+type FuzzProperties struct {
+ // Optional list of seed files to be installed to the fuzz target's output
+ // directory.
+ Corpus []string `android:"path"`
+ // Optional dictionary to be installed to the fuzz target's output directory.
+ Dictionary *string `android:"path"`
+}
+
func init() {
android.RegisterModuleType("cc_fuzz", FuzzFactory)
+ android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
}
// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
@@ -42,10 +52,15 @@
type fuzzBinary struct {
*binaryDecorator
*baseCompiler
+
+ Properties FuzzProperties
+ corpus android.Paths
+ dictionary android.Path
}
func (fuzz *fuzzBinary) linkerProps() []interface{} {
props := fuzz.binaryDecorator.linkerProps()
+ props = append(props, &fuzz.Properties)
return props
}
@@ -81,9 +96,21 @@
}
func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
- fuzz.binaryDecorator.baseInstaller.dir = filepath.Join("fuzz", ctx.Target().Arch.ArchType.String())
- fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join("fuzz", ctx.Target().Arch.ArchType.String())
+ fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
+ "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
+ "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
fuzz.binaryDecorator.baseInstaller.install(ctx, file)
+
+ fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
+ if fuzz.Properties.Dictionary != nil {
+ fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
+ if fuzz.dictionary.Ext() != ".dict" {
+ ctx.PropertyErrorf("dictionary",
+ "Fuzzer dictionary %q does not have '.dict' extension",
+ fuzz.dictionary.String())
+ }
+ }
}
func NewFuzz(hod android.HostOrDeviceSupported) *Module {
@@ -130,3 +157,95 @@
return module
}
+
+// Responsible for generating GNU Make rules that package fuzz targets into
+// their architecture & target/host specific zip file.
+type fuzzPackager struct {
+ packages android.Paths
+}
+
+func fuzzPackagingFactory() android.Singleton {
+ return &fuzzPackager{}
+}
+
+type fileToZip struct {
+ SourceFilePath android.Path
+ DestinationPathPrefix string
+}
+
+func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+ // Map between each architecture + host/device combination, and the files that
+ // need to be packaged (in the tuple of {source file, destination folder in
+ // archive}).
+ archDirs := make(map[android.OutputPath][]fileToZip)
+
+ ctx.VisitAllModules(func(module android.Module) {
+ // Discard non-fuzz targets.
+ ccModule, ok := module.(*Module)
+ if !ok {
+ return
+ }
+ fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
+ if !ok {
+ return
+ }
+
+ // Discard vendor-NDK-linked modules, they're duplicates of fuzz targets
+ // we're going to package anyway.
+ if ccModule.useVndk() || !ccModule.Enabled() {
+ return
+ }
+
+ hostOrTargetString := "target"
+ if ccModule.Host() {
+ hostOrTargetString = "host"
+ }
+
+ archString := ccModule.Arch().ArchType.String()
+ archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+
+ // The executable.
+ archDirs[archDir] = append(archDirs[archDir],
+ fileToZip{ccModule.outputFile.Path(), ccModule.Name()})
+
+ // The corpora.
+ for _, corpusEntry := range fuzzModule.corpus {
+ archDirs[archDir] = append(archDirs[archDir],
+ fileToZip{corpusEntry, ccModule.Name() + "/corpus/" + corpusEntry.Base()})
+ }
+
+ // The dictionary.
+ if fuzzModule.dictionary != nil {
+ archDirs[archDir] = append(archDirs[archDir],
+ fileToZip{fuzzModule.dictionary, ccModule.Name()})
+ }
+ })
+
+ for archDir, filesToZip := range archDirs {
+ arch := archDir.Base()
+ hostOrTarget := filepath.Base(filepath.Dir(archDir.String()))
+ builder := android.NewRuleBuilder()
+ outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
+ s.packages = append(s.packages, outputFile)
+
+ command := builder.Command().BuiltTool(ctx, "soong_zip").
+ Flag("-j").
+ FlagWithOutput("-o ", outputFile)
+
+ for _, fileToZip := range filesToZip {
+ command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix).
+ FlagWithInput("-f ", fileToZip.SourceFilePath)
+ }
+
+ builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
+ "Create fuzz target packages for "+arch+"-"+hostOrTarget)
+ }
+}
+
+func (s *fuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+ // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
+ // ready to handle phony targets created in Soong. In the meantime, this
+ // exports the phony 'fuzz' target and dependencies on packages to
+ // core/main.mk so that we can use dist-for-goals.
+ ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(s.packages.Strings(), " "))
+}
diff --git a/cc/gen.go b/cc/gen.go
index 42b0cbe..17ab45f 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -113,7 +113,14 @@
aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base())
baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext())
- shortName := strings.TrimPrefix(baseName, "I")
+ shortName := baseName
+ // TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if
+ // an interface name has a leading I. Those same heuristics have been
+ // moved here.
+ if len(baseName) >= 2 && baseName[0] == 'I' &&
+ strings.ToUpper(baseName)[1] == baseName[1] {
+ shortName = strings.TrimPrefix(baseName, "I")
+ }
outDir := android.PathForModuleGen(ctx, "aidl")
headerI := outDir.Join(ctx, aidlPackage, baseName+".h")
diff --git a/cc/library.go b/cc/library.go
index c402ea0..a41ddc2 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -31,24 +31,7 @@
"android/soong/genrule"
)
-type StaticSharedLibraryProperties struct {
- Srcs []string `android:"path,arch_variant"`
- Cflags []string `android:"arch_variant"`
-
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
- System_shared_libs []string `android:"arch_variant"`
-
- Export_shared_lib_headers []string `android:"arch_variant"`
- Export_static_lib_headers []string `android:"arch_variant"`
-}
-
type LibraryProperties struct {
- Static StaticSharedLibraryProperties `android:"arch_variant"`
- Shared StaticSharedLibraryProperties `android:"arch_variant"`
-
// local file name to pass to the linker as -unexported_symbols_list
Unexported_symbols_list *string `android:"path,arch_variant"`
// local file name to pass to the linker as -force_symbols_not_weak_list
@@ -128,6 +111,28 @@
Inject_bssl_hash *bool `android:"arch_variant"`
}
+type StaticProperties struct {
+ Static StaticOrSharedProperties `android:"arch_variant"`
+}
+
+type SharedProperties struct {
+ Shared StaticOrSharedProperties `android:"arch_variant"`
+}
+
+type StaticOrSharedProperties struct {
+ Srcs []string `android:"path,arch_variant"`
+ Cflags []string `android:"arch_variant"`
+
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ System_shared_libs []string `android:"arch_variant"`
+
+ Export_shared_lib_headers []string `android:"arch_variant"`
+ Export_static_lib_headers []string `android:"arch_variant"`
+}
+
type LibraryMutatedProperties struct {
// Build a static variant
BuildStatic bool `blueprint:"mutated"`
@@ -295,6 +300,8 @@
// functionality: static vs. shared linkage, reusing object files for shared libraries
type libraryDecorator struct {
Properties LibraryProperties
+ StaticProperties StaticProperties
+ SharedProperties SharedProperties
MutatedProperties LibraryMutatedProperties
// For reusing static library objects for shared library
@@ -355,11 +362,20 @@
func (library *libraryDecorator) linkerProps() []interface{} {
var props []interface{}
props = append(props, library.baseLinker.linkerProps()...)
- return append(props,
+ props = append(props,
&library.Properties,
&library.MutatedProperties,
&library.flagExporter.Properties,
&library.stripper.StripProperties)
+
+ if library.MutatedProperties.BuildShared {
+ props = append(props, &library.SharedProperties)
+ }
+ if library.MutatedProperties.BuildStatic {
+ props = append(props, &library.StaticProperties)
+ }
+
+ return props
}
func (library *libraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -373,9 +389,9 @@
}
if library.static() {
- flags.CFlags = append(flags.CFlags, library.Properties.Static.Cflags...)
+ flags.CFlags = append(flags.CFlags, library.StaticProperties.Static.Cflags...)
} else if library.shared() {
- flags.CFlags = append(flags.CFlags, library.Properties.Shared.Cflags...)
+ flags.CFlags = append(flags.CFlags, library.SharedProperties.Shared.Cflags...)
}
if library.shared() {
@@ -498,10 +514,10 @@
if len(library.baseCompiler.Properties.Srcs) > 0 {
ctx.PropertyErrorf("srcs", "cc_library_headers must not have any srcs")
}
- if len(library.Properties.Static.Srcs) > 0 {
+ if len(library.StaticProperties.Static.Srcs) > 0 {
ctx.PropertyErrorf("static.srcs", "cc_library_headers must not have any srcs")
}
- if len(library.Properties.Shared.Srcs) > 0 {
+ if len(library.SharedProperties.Shared.Srcs) > 0 {
ctx.PropertyErrorf("shared.srcs", "cc_library_headers must not have any srcs")
}
return Objects{}
@@ -516,8 +532,8 @@
SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
}
flags.SAbiFlags = SourceAbiFlags
- total_length := len(library.baseCompiler.Properties.Srcs) + len(deps.GeneratedSources) + len(library.Properties.Shared.Srcs) +
- len(library.Properties.Static.Srcs)
+ total_length := len(library.baseCompiler.Properties.Srcs) + len(deps.GeneratedSources) +
+ len(library.SharedProperties.Shared.Srcs) + len(library.StaticProperties.Static.Srcs)
if total_length > 0 {
flags.SAbiDump = true
}
@@ -527,11 +543,11 @@
buildFlags := flagsToBuilderFlags(flags)
if library.static() {
- srcs := android.PathsForModuleSrc(ctx, library.Properties.Static.Srcs)
+ srcs := android.PathsForModuleSrc(ctx, library.StaticProperties.Static.Srcs)
objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceStaticLibrary,
srcs, library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
} else if library.shared() {
- srcs := android.PathsForModuleSrc(ctx, library.Properties.Shared.Srcs)
+ srcs := android.PathsForModuleSrc(ctx, library.SharedProperties.Shared.Srcs)
objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceSharedLibrary,
srcs, library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
}
@@ -625,12 +641,12 @@
func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
if library.static() {
- if library.Properties.Static.System_shared_libs != nil {
- library.baseLinker.Properties.System_shared_libs = library.Properties.Static.System_shared_libs
+ if library.StaticProperties.Static.System_shared_libs != nil {
+ library.baseLinker.Properties.System_shared_libs = library.StaticProperties.Static.System_shared_libs
}
} else if library.shared() {
- if library.Properties.Shared.System_shared_libs != nil {
- library.baseLinker.Properties.System_shared_libs = library.Properties.Shared.System_shared_libs
+ if library.SharedProperties.Shared.System_shared_libs != nil {
+ library.baseLinker.Properties.System_shared_libs = library.SharedProperties.Shared.System_shared_libs
}
}
@@ -638,12 +654,12 @@
if library.static() {
deps.WholeStaticLibs = append(deps.WholeStaticLibs,
- library.Properties.Static.Whole_static_libs...)
- deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
+ library.StaticProperties.Static.Whole_static_libs...)
+ deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs...)
+ deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs...)
- deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.Properties.Static.Export_shared_lib_headers...)
- deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.Properties.Static.Export_static_lib_headers...)
+ deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.StaticProperties.Static.Export_shared_lib_headers...)
+ deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.StaticProperties.Static.Export_static_lib_headers...)
} else if library.shared() {
if ctx.toolchain().Bionic() && !Bool(library.baseLinker.Properties.Nocrt) {
if !ctx.useSdk() {
@@ -662,12 +678,12 @@
deps.CrtEnd = "ndk_crtend_so." + version
}
}
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
- deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs...)
+ deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs...)
+ deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs...)
- deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.Properties.Shared.Export_shared_lib_headers...)
- deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.Properties.Shared.Export_static_lib_headers...)
+ deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.SharedProperties.Shared.Export_shared_lib_headers...)
+ deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.SharedProperties.Shared.Export_static_lib_headers...)
}
if ctx.useVndk() {
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
@@ -978,11 +994,13 @@
}
func (library *libraryDecorator) buildStatic() bool {
- return library.MutatedProperties.BuildStatic && BoolDefault(library.Properties.Static.Enabled, true)
+ return library.MutatedProperties.BuildStatic &&
+ BoolDefault(library.StaticProperties.Static.Enabled, true)
}
func (library *libraryDecorator) buildShared() bool {
- return library.MutatedProperties.BuildShared && BoolDefault(library.Properties.Shared.Enabled, true)
+ return library.MutatedProperties.BuildShared &&
+ BoolDefault(library.SharedProperties.Shared.Enabled, true)
}
func (library *libraryDecorator) getWholeStaticMissingDeps() []string {
@@ -1166,16 +1184,16 @@
// Check libraries in addition to cflags, since libraries may be exporting different
// include directories.
- if len(staticCompiler.Properties.Static.Cflags) == 0 &&
- len(sharedCompiler.Properties.Shared.Cflags) == 0 &&
- len(staticCompiler.Properties.Static.Whole_static_libs) == 0 &&
- len(sharedCompiler.Properties.Shared.Whole_static_libs) == 0 &&
- len(staticCompiler.Properties.Static.Static_libs) == 0 &&
- len(sharedCompiler.Properties.Shared.Static_libs) == 0 &&
- len(staticCompiler.Properties.Static.Shared_libs) == 0 &&
- len(sharedCompiler.Properties.Shared.Shared_libs) == 0 &&
- staticCompiler.Properties.Static.System_shared_libs == nil &&
- sharedCompiler.Properties.Shared.System_shared_libs == nil {
+ if len(staticCompiler.StaticProperties.Static.Cflags) == 0 &&
+ len(sharedCompiler.SharedProperties.Shared.Cflags) == 0 &&
+ len(staticCompiler.StaticProperties.Static.Whole_static_libs) == 0 &&
+ len(sharedCompiler.SharedProperties.Shared.Whole_static_libs) == 0 &&
+ len(staticCompiler.StaticProperties.Static.Static_libs) == 0 &&
+ len(sharedCompiler.SharedProperties.Shared.Static_libs) == 0 &&
+ len(staticCompiler.StaticProperties.Static.Shared_libs) == 0 &&
+ len(sharedCompiler.SharedProperties.Shared.Shared_libs) == 0 &&
+ staticCompiler.StaticProperties.Static.System_shared_libs == nil &&
+ sharedCompiler.SharedProperties.Shared.System_shared_libs == nil {
mctx.AddInterVariantDependency(reuseObjTag, shared, static)
sharedCompiler.baseCompiler.Properties.OriginalSrcs =
@@ -1333,6 +1351,7 @@
rule := android.NewRuleBuilder()
rule.Command().
BuiltTool(ctx, "bssl_inject_hash").
+ Flag("-sha256").
FlagWithInput("-in-object ", outputFile).
FlagWithOutput("-o ", hashedOutputfile)
rule.Build(pctx, ctx, "injectCryptoHash", "inject crypto hash")
diff --git a/cc/linker.go b/cc/linker.go
index 563ad04..e5e1486 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -491,7 +491,7 @@
gen_sorted_bss_symbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
blueprint.RuleParams{
Command: "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}",
- CommandDeps: []string{"$genSortedBssSymbolsPath"},
+ CommandDeps: []string{"$genSortedBssSymbolsPath", "${crossCompile}nm"},
},
"crossCompile")
)
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 4d59975..9cbe800 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -76,7 +76,7 @@
}
func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
- vndk_ver := ctx.DeviceConfig().VndkVersion()
+ vndk_ver := ctx.Module().(*Module).Properties.VndkVersion
if vndk_ver == "current" {
platform_vndk_ver := ctx.DeviceConfig().PlatformVndkVersion()
if !inList(platform_vndk_ver, ctx.Config().PlatformVersionCombinedCodenames()) {
@@ -177,7 +177,6 @@
libraryDecorator: library,
}
stub.Properties.Vendor_available = BoolPtr(true)
- module.Properties.UseVndk = true
module.compiler = stub
module.linker = stub
module.installer = nil
diff --git a/cc/object.go b/cc/object.go
index 1a2711d..1f1ac8e 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -52,8 +52,9 @@
// input to a cc_genrule module.
func ObjectFactory() android.Module {
module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth)
+ module.sanitize = &sanitize{}
module.linker = &objectLinker{
- baseLinker: NewBaseLinker(nil),
+ baseLinker: NewBaseLinker(module.sanitize),
}
module.compiler = NewBaseCompiler()
@@ -123,7 +124,7 @@
output = input
}
- TransformObjsToObj(ctx, objs.objFiles, builderFlags, output)
+ TransformObjsToObj(ctx, objs.objFiles, builderFlags, output, flags.LdFlagsDeps)
}
ctx.CheckbuildFile(outputFile)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index a7d0308..4e6cdd7 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -19,8 +19,8 @@
)
func init() {
- android.RegisterModuleType("cc_prebuilt_library_shared", prebuiltSharedLibraryFactory)
- android.RegisterModuleType("cc_prebuilt_library_static", prebuiltStaticLibraryFactory)
+ android.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
+ android.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
android.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
}
@@ -131,7 +131,7 @@
// cc_prebuilt_library_shared installs a precompiled shared library that are
// listed in the srcs property in the device's directory.
-func prebuiltSharedLibraryFactory() android.Module {
+func PrebuiltSharedLibraryFactory() android.Module {
module, _ := NewPrebuiltSharedLibrary(android.HostAndDeviceSupported)
return module.Init()
}
@@ -152,13 +152,14 @@
// Prebuilt libraries can be included in APEXes
android.InitApexModule(module)
+ android.InitSdkAwareModule(module)
return module, library
}
// cc_prebuilt_library_static installs a precompiled static library that are
// listed in the srcs property in the device's directory.
-func prebuiltStaticLibraryFactory() android.Module {
+func PrebuiltStaticLibraryFactory() android.Module {
module, _ := NewPrebuiltStaticLibrary(android.HostAndDeviceSupported)
return module.Init()
}
@@ -176,6 +177,7 @@
module.AddProperties(&prebuilt.properties)
android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
+ android.InitSdkAwareModule(module)
return module, library
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 98d78e8..edcd26e 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -72,8 +72,8 @@
ctx := CreateTestContext(bp, fs, android.Android)
- ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(prebuiltSharedLibraryFactory))
- ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(prebuiltStaticLibraryFactory))
+ ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(PrebuiltSharedLibraryFactory))
+ ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(PrebuiltStaticLibraryFactory))
ctx.RegisterModuleType("cc_prebuilt_binary", android.ModuleFactoryAdaptor(prebuiltBinaryFactory))
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 415518c..c0a7c63 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -674,7 +674,7 @@
func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
t, ok := tag.(dependencyTag)
- return ok && t.library || t == reuseObjTag
+ return ok && t.library || t == reuseObjTag || t == objDepTag
}
// Propagate sanitizer requirements down from binaries
diff --git a/cc/strip.go b/cc/strip.go
index f3e3374..7e560ec 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -27,7 +27,6 @@
Keep_symbols *bool `android:"arch_variant"`
Keep_symbols_list []string `android:"arch_variant"`
Keep_symbols_and_debug_frame *bool `android:"arch_variant"`
- Use_gnu_strip *bool `android:"arch_variant"`
} `android:"arch_variant"`
}
@@ -54,9 +53,6 @@
} else if !Bool(stripper.StripProperties.Strip.All) {
flags.stripKeepMiniDebugInfo = true
}
- if Bool(stripper.StripProperties.Strip.Use_gnu_strip) {
- flags.stripUseGnuStrip = true
- }
if ctx.Config().Debuggable() && !flags.stripKeepMiniDebugInfo && !isStaticLib {
flags.stripAddGnuDebuglink = true
}
diff --git a/cc/test.go b/cc/test.go
index 1a0d44f..0e66e28 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "strconv"
"strings"
"android/soong/android"
@@ -71,6 +72,19 @@
// Add RunCommandTargetPreparer to stop framework before the test and start it after the test.
Disable_framework *bool
+
+ // Add MinApiLevelModuleController to auto generated test config. If the device property of
+ // "ro.product.first_api_level" < Test_min_api_level, then skip this module.
+ Test_min_api_level *int64
+
+ // Add MinApiLevelModuleController to auto generated test config. If the device property of
+ // "ro.build.version.sdk" < Test_min_sdk_version, then skip this module.
+ Test_min_sdk_version *int64
+
+ // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+ // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+ // explicitly.
+ Auto_gen_config *bool
}
func init() {
@@ -314,15 +328,21 @@
func (test *testBinary) install(ctx ModuleContext, file android.Path) {
test.data = android.PathsForModuleSrc(ctx, test.Properties.Data)
+ var api_level_prop string
var configs []tradefed.Config
+ var min_level string
if Bool(test.Properties.Require_root) {
- configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RootTargetPreparer", nil})
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
+ } else {
+ var options []tradefed.Option
+ options = append(options, tradefed.Option{"force-root", "false"})
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
}
if Bool(test.Properties.Disable_framework) {
var options []tradefed.Option
options = append(options, tradefed.Option{"run-command", "stop"})
options = append(options, tradefed.Option{"teardown-command", "start"})
- configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RunCommandTargetPreparer", options})
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RunCommandTargetPreparer", options})
}
if Bool(test.testDecorator.Properties.Isolated) {
configs = append(configs, tradefed.Option{"not-shardable", "true"})
@@ -330,9 +350,24 @@
if test.Properties.Test_options.Run_test_as != nil {
configs = append(configs, tradefed.Option{"run-test-as", String(test.Properties.Test_options.Run_test_as)})
}
+ if test.Properties.Test_min_api_level != nil && test.Properties.Test_min_sdk_version != nil {
+ ctx.PropertyErrorf("test_min_api_level", "'test_min_api_level' and 'test_min_sdk_version' should not be set at the same time.")
+ } else if test.Properties.Test_min_api_level != nil {
+ api_level_prop = "ro.product.first_api_level"
+ min_level = strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)
+ } else if test.Properties.Test_min_sdk_version != nil {
+ api_level_prop = "ro.build.version.sdk"
+ min_level = strconv.FormatInt(int64(*test.Properties.Test_min_sdk_version), 10)
+ }
+ if api_level_prop != "" {
+ var options []tradefed.Option
+ options = append(options, tradefed.Option{"min-api-level", min_level})
+ options = append(options, tradefed.Option{"api-level-prop", api_level_prop})
+ configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
+ }
test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
- test.Properties.Test_config_template, test.Properties.Test_suites, configs)
+ test.Properties.Test_config_template, test.Properties.Test_suites, configs, test.Properties.Auto_gen_config)
test.binaryDecorator.baseInstaller.dir = "nativetest"
test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
@@ -423,6 +458,11 @@
// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
// with root permission.
Require_root *bool
+
+ // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+ // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+ // explicitly.
+ Auto_gen_config *bool
}
type benchmarkDecorator struct {
@@ -457,10 +497,10 @@
benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data)
var configs []tradefed.Config
if Bool(benchmark.Properties.Require_root) {
- configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RootTargetPreparer", nil})
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
}
benchmark.testConfig = tradefed.AutoGenNativeBenchmarkTestConfig(ctx, benchmark.Properties.Test_config,
- benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites, configs)
+ benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites, configs, benchmark.Properties.Auto_gen_config)
benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName())
benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())
diff --git a/cc/testing.go b/cc/testing.go
index 5a3993c..11a5e3b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -239,6 +239,7 @@
os android.OsType) *android.TestContext {
ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("cc_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(BinaryFactory))
ctx.RegisterModuleType("cc_binary_host", android.ModuleFactoryAdaptor(binaryHostFactory))
ctx.RegisterModuleType("cc_fuzz", android.ModuleFactoryAdaptor(FuzzFactory))
@@ -253,7 +254,7 @@
ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
- ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(vndkPrebuiltSharedFactory))
+ ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(VndkPrebuiltSharedFactory))
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("image", ImageMutator).Parallel()
ctx.BottomUp("link", LinkageMutator).Parallel()
@@ -264,6 +265,7 @@
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
})
+ ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.RegisterSingletonType("vndk-snapshot", android.SingletonFactoryAdaptor(VndkSnapshotSingleton))
// add some modules that are required by the compiler and/or linker
@@ -274,6 +276,7 @@
"foo.c": nil,
"foo.lds": nil,
"bar.c": nil,
+ "baz.c": nil,
"baz.o": nil,
"a.proto": nil,
"b.aidl": nil,
diff --git a/cc/vndk.go b/cc/vndk.go
index 698fab5..14bbf11 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -49,10 +49,6 @@
// Extending another module
Extends *string
-
- // for vndk_prebuilt_shared, this is set by "version" property.
- // Otherwise, this is set as PLATFORM_VNDK_VERSION.
- Version string `blueprint:"mutated"`
}
}
@@ -129,7 +125,7 @@
// Other (static and LL-NDK) libraries are allowed to link.
return
}
- if !to.Properties.UseVndk {
+ if !to.useVndk() {
ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
vndk.typeName(), to.Name())
return
@@ -325,14 +321,6 @@
return
}
- if m.isVndk() {
- if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
- m.vndkdep.Properties.Vndk.Version = lib.version()
- } else {
- m.vndkdep.Properties.Vndk.Version = mctx.DeviceConfig().PlatformVndkVersion()
- }
- }
-
if _, ok := m.linker.(*llndkStubDecorator); ok {
processLlndkLibrary(mctx, m)
return
@@ -341,8 +329,8 @@
lib, is_lib := m.linker.(*libraryDecorator)
prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
- if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
- if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
+ if (is_lib && lib.buildShared()) || (is_prebuilt_lib && prebuilt_lib.buildShared()) {
+ if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
processVndkLibrary(mctx, m)
return
}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index da357ed..8126e4a 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -167,13 +167,19 @@
module.stl = nil
module.sanitize = nil
library.StripProperties.Strip.None = BoolPtr(true)
- module.Properties.UseVndk = true
prebuilt := &vndkPrebuiltLibraryDecorator{
libraryDecorator: library,
}
prebuilt.properties.Check_elf_files = BoolPtr(false)
+ prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
+ prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
+
+ // Prevent default system libs (libc, libm, and libdl) from being linked
+ if prebuilt.baseLinker.Properties.System_shared_libs == nil {
+ prebuilt.baseLinker.Properties.System_shared_libs = []string{}
+ }
module.compiler = nil
module.linker = prebuilt
@@ -206,11 +212,11 @@
// },
// },
// }
-func vndkPrebuiltSharedFactory() android.Module {
+func VndkPrebuiltSharedFactory() android.Module {
module := vndkPrebuiltSharedLibrary()
return module.Init()
}
func init() {
- android.RegisterModuleType("vndk_prebuilt_shared", vndkPrebuiltSharedFactory)
+ android.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
}
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 1171a65..2800ade 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -158,7 +158,7 @@
func main() {
stdio := terminal.StdioImpl{}
- output := terminal.NewStatusOutput(stdio.Stdout(), "",
+ output := terminal.NewStatusOutput(stdio.Stdout(), "", false,
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
log := logger.New(output)
@@ -391,7 +391,7 @@
Thread: mpctx.Tracer.NewThread(product),
Status: &status.Status{},
}}
- ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "",
+ ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "", false,
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
config := build.NewConfig(ctx, flag.Args()...)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index ec4f90e..974c644 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -41,6 +41,12 @@
// description for the flag (to display when running help)
description string
+ // Forces the status output into dumb terminal mode.
+ forceDumbOutput bool
+
+ // Sets a prefix string to use for filenames of log files.
+ logsPrefix string
+
// Creates the build configuration based on the args and build context.
config func(ctx build.Context, args ...string) build.Config
@@ -64,17 +70,21 @@
stdio: stdio,
run: make,
}, {
- flag: "--dumpvar-mode",
- description: "print the value of the legacy make variable VAR to stdout",
- config: dumpVarConfig,
- stdio: customStdio,
- run: dumpVar,
+ flag: "--dumpvar-mode",
+ description: "print the value of the legacy make variable VAR to stdout",
+ forceDumbOutput: true,
+ logsPrefix: "dumpvars-",
+ config: dumpVarConfig,
+ stdio: customStdio,
+ run: dumpVar,
}, {
- flag: "--dumpvars-mode",
- description: "dump the values of one or more legacy make variables, in shell syntax",
- config: dumpVarConfig,
- stdio: customStdio,
- run: dumpVars,
+ flag: "--dumpvars-mode",
+ description: "dump the values of one or more legacy make variables, in shell syntax",
+ forceDumbOutput: true,
+ logsPrefix: "dumpvars-",
+ config: dumpVarConfig,
+ stdio: customStdio,
+ run: dumpVars,
}, {
flag: "--build-mode",
description: "build modules based on the specified build action",
@@ -113,7 +123,7 @@
os.Exit(1)
}
- output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"),
+ output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.forceDumbOutput,
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
log := logger.New(output)
@@ -157,14 +167,14 @@
}
os.MkdirAll(logsDir, 0777)
- log.SetOutput(filepath.Join(logsDir, "soong.log"))
- trace.SetOutput(filepath.Join(logsDir, "build.trace"))
- stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, "verbose.log")))
- stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, "error.log")))
- stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, "build_error")))
+ log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
+ trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
+ stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
+ stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
+ stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
stat.AddOutput(status.NewCriticalPath(log))
- defer met.Dump(filepath.Join(logsDir, "soong_metrics"))
+ defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
if !strings.HasSuffix(start, "N") {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 7f1fe42..78f2f3f 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -16,17 +16,30 @@
import (
"android/soong/android"
+ "fmt"
"reflect"
"strings"
"testing"
)
-func testModuleConfig(ctx android.PathContext) ModuleConfig {
+func testSystemModuleConfig(ctx android.PathContext, name string) ModuleConfig {
+ return testModuleConfig(ctx, name, "system")
+}
+
+func testSystemProductModuleConfig(ctx android.PathContext, name string) ModuleConfig {
+ return testModuleConfig(ctx, name, "system/product")
+}
+
+func testProductModuleConfig(ctx android.PathContext, name string) ModuleConfig {
+ return testModuleConfig(ctx, name, "product")
+}
+
+func testModuleConfig(ctx android.PathContext, name, partition string) ModuleConfig {
return ModuleConfig{
- Name: "test",
- DexLocation: "/system/app/test/test.apk",
- BuildPath: android.PathForOutput(ctx, "test/test.apk"),
- DexPath: android.PathForOutput(ctx, "test/dex/test.jar"),
+ Name: name,
+ DexLocation: fmt.Sprintf("/%s/app/test/%s.apk", partition, name),
+ BuildPath: android.PathForOutput(ctx, fmt.Sprintf("%s/%s.apk", name, name)),
+ DexPath: android.PathForOutput(ctx, fmt.Sprintf("%s/dex/%s.jar", name, name)),
UncompressedDex: false,
HasApkLibraries: false,
PreoptFlags: nil,
@@ -46,14 +59,14 @@
ForceCreateAppImage: false,
PresignedPrebuilt: false,
NoStripping: false,
- StripInputPath: android.PathForOutput(ctx, "unstripped/test.apk"),
- StripOutputPath: android.PathForOutput(ctx, "stripped/test.apk"),
+ StripInputPath: android.PathForOutput(ctx, fmt.Sprintf("unstripped/%s.apk", name)),
+ StripOutputPath: android.PathForOutput(ctx, fmt.Sprintf("stripped/%s.apk", name)),
}
}
func TestDexPreopt(t *testing.T) {
ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
- global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+ global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
rule, err := GenerateDexpreoptRule(ctx, global, module)
if err != nil {
@@ -73,7 +86,7 @@
func TestDexPreoptStrip(t *testing.T) {
// Test that we panic if we strip in a configuration where stripping is not allowed.
ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
- global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+ global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
global.NeverAllowStripping = true
module.NoStripping = false
@@ -86,29 +99,65 @@
func TestDexPreoptSystemOther(t *testing.T) {
ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
- global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+ global := GlobalConfigForTests(ctx)
+ systemModule := testSystemModuleConfig(ctx, "Stest")
+ systemProductModule := testSystemProductModuleConfig(ctx, "SPtest")
+ productModule := testProductModuleConfig(ctx, "Ptest")
global.HasSystemOther = true
- global.PatternsOnSystemOther = []string{"app/%"}
- rule, err := GenerateDexpreoptRule(ctx, global, module)
- if err != nil {
- t.Fatal(err)
+ type moduleTest struct {
+ module ModuleConfig
+ expectedPartition string
+ }
+ tests := []struct {
+ patterns []string
+ moduleTests []moduleTest
+ }{
+ {
+ patterns: []string{"app/%"},
+ moduleTests: []moduleTest{
+ {module: systemModule, expectedPartition: "system_other"},
+ {module: systemProductModule, expectedPartition: "system/product"},
+ {module: productModule, expectedPartition: "product"},
+ },
+ },
+ // product/app/% only applies to product apps inside the system partition
+ {
+ patterns: []string{"app/%", "product/app/%"},
+ moduleTests: []moduleTest{
+ {module: systemModule, expectedPartition: "system_other"},
+ {module: systemProductModule, expectedPartition: "system_other/product"},
+ {module: productModule, expectedPartition: "product"},
+ },
+ },
}
- wantInstalls := android.RuleBuilderInstalls{
- {android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system_other/app/test/oat/arm/test.odex"},
- {android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system_other/app/test/oat/arm/test.vdex"},
+ for _, test := range tests {
+ global.PatternsOnSystemOther = test.patterns
+ for _, mt := range test.moduleTests {
+ rule, err := GenerateDexpreoptRule(ctx, global, mt.module)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ name := mt.module.Name
+ wantInstalls := android.RuleBuilderInstalls{
+ {android.PathForOutput(ctx, name+"/oat/arm/package.odex"), fmt.Sprintf("/%s/app/test/oat/arm/%s.odex", mt.expectedPartition, name)},
+ {android.PathForOutput(ctx, name+"/oat/arm/package.vdex"), fmt.Sprintf("/%s/app/test/oat/arm/%s.vdex", mt.expectedPartition, name)},
+ }
+
+ if rule.Installs().String() != wantInstalls.String() {
+ t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
+ }
+ }
}
- if rule.Installs().String() != wantInstalls.String() {
- t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
- }
}
func TestDexPreoptProfile(t *testing.T) {
ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
- global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+ global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile"))
@@ -156,7 +205,7 @@
t.Run(test.name, func(t *testing.T) {
ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
- global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+ global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
test.setup(&global, &module)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index cf0b484..b8b0e01 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -437,7 +437,7 @@
phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
ctx.Build(pctx, android.BuildParams{
- Rule: android.Phony,
+ Rule: blueprint.Phony,
Output: phonyFile,
Inputs: g.outputFiles,
})
diff --git a/java/aapt2.go b/java/aapt2.go
index f0eb99c..cfe0dea 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -63,7 +63,7 @@
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
flags []string) android.WritablePaths {
- shards := shardPaths(paths, AAPT2_SHARD_SIZE)
+ shards := android.ShardPaths(paths, AAPT2_SHARD_SIZE)
ret := make(android.WritablePaths, 0, len(paths))
diff --git a/java/androidmk.go b/java/androidmk.go
index 0e8e422..bc61297 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -22,7 +22,9 @@
"android/soong/android"
)
-func (library *Library) AndroidMkHostDex(w io.Writer, name string, data android.AndroidMkData) {
+// TODO(jungjw): We'll probably want AndroidMkEntriesProvider.AndroidMkEntries to return multiple
+// entries so that this can be more error-proof.
+func (library *Library) AndroidMkHostDex(w io.Writer, name string, entries *android.AndroidMkEntries) {
if Bool(library.deviceProperties.Hostdex) && !library.Host() {
fmt.Fprintln(w, "include $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_MODULE := "+name+"-hostdex")
@@ -38,14 +40,14 @@
}
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String())
fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", library.implementationAndResourcesJar.String())
- if len(data.Required) > 0 {
- fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(data.Required, " "))
+ if len(entries.Required) > 0 {
+ fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(entries.Required, " "))
}
- if len(data.Host_required) > 0 {
- fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES :=", strings.Join(data.Host_required, " "))
+ if len(entries.Host_required) > 0 {
+ fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES :=", strings.Join(entries.Host_required, " "))
}
- if len(data.Target_required) > 0 {
- fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=", strings.Join(data.Target_required, " "))
+ if len(entries.Target_required) > 0 {
+ fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=", strings.Join(entries.Target_required, " "))
}
if r := library.deviceProperties.Target.Hostdex.Required; len(r) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(r, " "))
@@ -54,75 +56,64 @@
}
}
-func (library *Library) AndroidMk() android.AndroidMkData {
+func (library *Library) AndroidMkEntries() android.AndroidMkEntries {
if !library.IsForPlatform() {
- return android.AndroidMkData{
+ return android.AndroidMkEntries{
Disabled: true,
}
}
- return android.AndroidMkData{
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(library.outputFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
if len(library.logtagsSrcs) > 0 {
var logtags []string
for _, l := range library.logtagsSrcs {
logtags = append(logtags, l.Rel())
}
- fmt.Fprintln(w, "LOCAL_LOGTAGS_FILES :=", strings.Join(logtags, " "))
+ entries.AddStrings("LOCAL_LOGTAGS_FILES", logtags...)
}
if library.installFile == nil {
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
}
if library.dexJarFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", library.dexJarFile.String())
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile)
}
if len(library.dexpreopter.builtInstalled) > 0 {
- fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", library.dexpreopter.builtInstalled)
+ entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", library.dexpreopter.builtInstalled)
}
- fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", library.sdkVersion())
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", library.implementationAndResourcesJar.String())
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String())
+ entries.SetString("LOCAL_SDK_VERSION", library.sdkVersion())
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
if library.jacocoReportClassesFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", library.jacocoReportClassesFile.String())
+ entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
}
- if len(library.exportedSdkLibs) != 0 {
- fmt.Fprintln(w, "LOCAL_EXPORT_SDK_LIBRARIES :=", strings.Join(library.exportedSdkLibs, " "))
- }
+ entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...)
if len(library.additionalCheckedModules) != 0 {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_CHECKED_MODULE +=", strings.Join(library.additionalCheckedModules.Strings(), " "))
+ entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
}
if library.proguardDictionary != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", library.proguardDictionary.String())
+ entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
}
},
},
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- android.WriteAndroidMkData(w, data)
- library.AndroidMkHostDex(w, name, data)
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ library.AndroidMkHostDex(w, name, entries)
+ },
},
}
}
// Called for modules that are a component of a test suite.
-func testSuiteComponent(w io.Writer, test_suites []string) {
- fmt.Fprintln(w, "LOCAL_MODULE_TAGS := tests")
- if len(test_suites) > 0 {
- fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
- strings.Join(test_suites, " "))
- } else {
- fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := null-suite")
- }
-}
-
-func testSuiteComponentEntries(entries *android.AndroidMkEntries, test_suites []string) {
+func testSuiteComponent(entries *android.AndroidMkEntries, test_suites []string) {
entries.SetString("LOCAL_MODULE_TAGS", "tests")
if len(test_suites) > 0 {
entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", test_suites...)
@@ -131,179 +122,175 @@
}
}
-func (j *Test) AndroidMk() android.AndroidMkData {
- data := j.Library.AndroidMk()
- data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
- testSuiteComponent(w, j.testProperties.Test_suites)
+func (j *Test) AndroidMkEntries() android.AndroidMkEntries {
+ entries := j.Library.AndroidMkEntries()
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ testSuiteComponent(entries, j.testProperties.Test_suites)
if j.testConfig != nil {
- fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", j.testConfig.String())
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", j.testConfig)
}
+ androidMkWriteTestData(j.data, entries)
})
- androidMkWriteTestData(j.data, &data)
-
- return data
+ return entries
}
-func (j *TestHelperLibrary) AndroidMk() android.AndroidMkData {
- data := j.Library.AndroidMk()
- data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
- testSuiteComponent(w, j.testHelperLibraryProperties.Test_suites)
+func (j *TestHelperLibrary) AndroidMkEntries() android.AndroidMkEntries {
+ entries := j.Library.AndroidMkEntries()
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ testSuiteComponent(entries, j.testHelperLibraryProperties.Test_suites)
})
- return data
+ return entries
}
-func (prebuilt *Import) AndroidMk() android.AndroidMkData {
- if !prebuilt.IsForPlatform() {
- return android.AndroidMkData{
+func (prebuilt *Import) AndroidMkEntries() android.AndroidMkEntries {
+ if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().IsCurrentVersion() {
+ return android.AndroidMkEntries{
Disabled: true,
}
}
- return android.AndroidMkData{
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := ", !Bool(prebuilt.properties.Installable))
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.combinedClasspathFile.String())
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", prebuilt.combinedClasspathFile.String())
- fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", prebuilt.sdkVersion())
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
+ entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion())
},
},
}
}
-func (prebuilt *DexImport) AndroidMk() android.AndroidMkData {
+func (prebuilt *DexImport) AndroidMkEntries() android.AndroidMkEntries {
if !prebuilt.IsForPlatform() {
- return android.AndroidMkData{
+ return android.AndroidMkEntries{
Disabled: true,
}
}
- return android.AndroidMkData{
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(prebuilt.maybeStrippedDexJarFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
if prebuilt.dexJarFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", prebuilt.dexJarFile.String())
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
// TODO(b/125517186): export the dex jar as a classes jar to match some mis-uses in Make until
// boot_jars_package_check.mk can check dex jars.
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.dexJarFile.String())
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", prebuilt.dexJarFile.String())
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.dexJarFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.dexJarFile)
}
if len(prebuilt.dexpreopter.builtInstalled) > 0 {
- fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", prebuilt.dexpreopter.builtInstalled)
+ entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", prebuilt.dexpreopter.builtInstalled)
}
},
},
}
}
-func (prebuilt *AARImport) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
+func (prebuilt *AARImport) AndroidMkEntries() android.AndroidMkEntries {
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.classpathFile.String())
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", prebuilt.classpathFile.String())
- fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", prebuilt.exportPackage.String())
- fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=", prebuilt.proguardFlags.String())
- fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", prebuilt.extraAaptPackagesFile.String())
- fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", prebuilt.manifest.String())
- fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", prebuilt.sdkVersion())
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile)
+ entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage)
+ entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
+ entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", prebuilt.extraAaptPackagesFile)
+ entries.SetPath("LOCAL_FULL_MANIFEST_FILE", prebuilt.manifest)
+ entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion())
},
},
}
}
-func (binary *Binary) AndroidMk() android.AndroidMkData {
+func (binary *Binary) AndroidMkEntries() android.AndroidMkEntries {
if !binary.isWrapperVariant {
- return android.AndroidMkData{
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(binary.outputFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", binary.headerJarFile.String())
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", binary.implementationAndResourcesJar.String())
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", binary.headerJarFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", binary.implementationAndResourcesJar)
if binary.dexJarFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", binary.dexJarFile.String())
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", binary.dexJarFile)
}
if len(binary.dexpreopter.builtInstalled) > 0 {
- fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", binary.dexpreopter.builtInstalled)
+ entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
}
},
},
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- android.WriteAndroidMkData(w, data)
-
- fmt.Fprintln(w, "jar_installed_module := $(LOCAL_INSTALLED_MODULE)")
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ fmt.Fprintln(w, "jar_installed_module := $(LOCAL_INSTALLED_MODULE)")
+ },
},
}
} else {
- return android.AndroidMkData{
+ return android.AndroidMkEntries{
Class: "EXECUTABLES",
OutputFile: android.OptionalPathForPath(binary.wrapperFile),
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_STRIP_MODULE := false")
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_STRIP_MODULE", false)
},
},
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- android.WriteAndroidMkData(w, data)
-
- // Ensure that the wrapper script timestamp is always updated when the jar is updated
- fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): $(jar_installed_module)")
- fmt.Fprintln(w, "jar_installed_module :=")
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ // Ensure that the wrapper script timestamp is always updated when the jar is updated
+ fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): $(jar_installed_module)")
+ fmt.Fprintln(w, "jar_installed_module :=")
+ },
},
}
}
}
-func (app *AndroidApp) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
+func (app *AndroidApp) AndroidMkEntries() android.AndroidMkEntries {
+ return android.AndroidMkEntries{
Class: "APPS",
OutputFile: android.OptionalPathForPath(app.outputFile),
Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
- // TODO(jungjw): This, outputting two LOCAL_MODULE lines, works, but is not ideal. Find a better solution.
- if app.Name() != app.installApkName {
- fmt.Fprintln(w, "# Overridden by PRODUCT_PACKAGE_NAME_OVERRIDES")
- fmt.Fprintln(w, "LOCAL_MODULE :=", app.installApkName)
- }
- fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", app.exportPackage.String())
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ // App module names can be overridden.
+ entries.SetString("LOCAL_MODULE", app.installApkName)
+ entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", app.exportPackage)
if app.dexJarFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", app.dexJarFile.String())
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile)
}
if app.implementationAndResourcesJar != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", app.implementationAndResourcesJar.String())
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", app.implementationAndResourcesJar)
}
if app.headerJarFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", app.headerJarFile.String())
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", app.headerJarFile)
}
if app.bundleFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_BUNDLE :=", app.bundleFile.String())
+ entries.SetPath("LOCAL_SOONG_BUNDLE", app.bundleFile)
}
if app.jacocoReportClassesFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
+ entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", app.jacocoReportClassesFile)
}
if app.proguardDictionary != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", app.proguardDictionary.String())
+ entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.proguardDictionary)
}
if app.Name() == "framework-res" {
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
+ entries.SetString("LOCAL_MODULE_PATH", "$(TARGET_OUT_JAVA_LIBRARIES)")
// Make base_rules.mk not put framework-res in a subdirectory called
// framework_res.
- fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true")
+ entries.SetBoolIfTrue("LOCAL_NO_STANDARD_LIBRARIES", true)
}
filterRRO := func(filter overlayType) android.Paths {
@@ -319,38 +306,37 @@
}
deviceRRODirs := filterRRO(device)
if len(deviceRRODirs) > 0 {
- fmt.Fprintln(w, "LOCAL_SOONG_DEVICE_RRO_DIRS :=", strings.Join(deviceRRODirs.Strings(), " "))
+ entries.AddStrings("LOCAL_SOONG_DEVICE_RRO_DIRS", deviceRRODirs.Strings()...)
}
productRRODirs := filterRRO(product)
if len(productRRODirs) > 0 {
- fmt.Fprintln(w, "LOCAL_SOONG_PRODUCT_RRO_DIRS :=", strings.Join(productRRODirs.Strings(), " "))
+ entries.AddStrings("LOCAL_SOONG_PRODUCT_RRO_DIRS", productRRODirs.Strings()...)
}
- if Bool(app.appProperties.Export_package_resources) {
- fmt.Fprintln(w, "LOCAL_EXPORT_PACKAGE_RESOURCES := true")
- }
+ entries.SetBoolIfTrue("LOCAL_EXPORT_PACKAGE_RESOURCES", Bool(app.appProperties.Export_package_resources))
- fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", app.manifestPath.String())
+ entries.SetPath("LOCAL_FULL_MANIFEST_FILE", app.manifestPath)
- if Bool(app.appProperties.Privileged) {
- fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true")
- }
+ entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", Bool(app.appProperties.Privileged))
- fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.Pem.String())
- if overriddenPkgs := app.getOverriddenPackages(); len(overriddenPkgs) > 0 {
- fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES :=", strings.Join(overriddenPkgs, " "))
- }
+ entries.SetPath("LOCAL_CERTIFICATE", app.certificate.Pem)
+ entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", app.getOverriddenPackages()...)
for _, jniLib := range app.installJniLibs {
- fmt.Fprintln(w, "LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), "+=", jniLib.name)
+ entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
}
if len(app.dexpreopter.builtInstalled) > 0 {
- fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", app.dexpreopter.builtInstalled)
+ entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", app.dexpreopter.builtInstalled)
}
for _, split := range app.aapt.splits {
- install := "$(LOCAL_MODULE_PATH)/" + strings.TrimSuffix(app.installApkName, ".apk") + split.suffix + ".apk"
- fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED +=", split.path.String()+":"+install)
+ install := app.onDeviceDir + "/" +
+ strings.TrimSuffix(app.installApkName, ".apk") + "_" + split.suffix + ".apk"
+ entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", split.path.String()+":"+install)
}
+ },
+ },
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
if app.noticeOutputs.Merged.Valid() {
fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
app.installApkName, app.noticeOutputs.Merged.String(), app.installApkName+"_NOTICE")
@@ -379,85 +365,116 @@
return overridden
}
-func (a *AndroidTest) AndroidMk() android.AndroidMkData {
- data := a.AndroidApp.AndroidMk()
- data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
- testSuiteComponent(w, a.testProperties.Test_suites)
+func (a *AndroidTest) AndroidMkEntries() android.AndroidMkEntries {
+ entries := a.AndroidApp.AndroidMkEntries()
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ testSuiteComponent(entries, a.testProperties.Test_suites)
if a.testConfig != nil {
- fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", a.testConfig.String())
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", a.testConfig)
}
- })
- androidMkWriteTestData(a.data, &data)
-
- return data
-}
-
-func (a *AndroidTestHelperApp) AndroidMk() android.AndroidMkData {
- data := a.AndroidApp.AndroidMk()
- data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
- testSuiteComponent(w, a.appTestHelperAppProperties.Test_suites)
+ androidMkWriteTestData(a.data, entries)
})
- return data
+ return entries
}
-func (a *AndroidLibrary) AndroidMk() android.AndroidMkData {
- data := a.Library.AndroidMk()
+func (a *AndroidTestHelperApp) AndroidMkEntries() android.AndroidMkEntries {
+ entries := a.AndroidApp.AndroidMkEntries()
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ testSuiteComponent(entries, a.appTestHelperAppProperties.Test_suites)
+ })
- data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
+ return entries
+}
+
+func (a *AndroidLibrary) AndroidMkEntries() android.AndroidMkEntries {
+ entries := a.Library.AndroidMkEntries()
+
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
if a.aarFile != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_AAR :=", a.aarFile.String())
+ entries.SetPath("LOCAL_SOONG_AAR", a.aarFile)
}
if a.Name() == "framework-res" {
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
+ entries.SetString("LOCAL_MODULE_PATH", "$(TARGET_OUT_JAVA_LIBRARIES)")
// Make base_rules.mk not put framework-res in a subdirectory called
// framework_res.
- fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true")
+ entries.SetBoolIfTrue("LOCAL_NO_STANDARD_LIBRARIES", true)
}
- fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", a.exportPackage.String())
- fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", a.extraAaptPackagesFile.String())
- fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", a.mergedManifestFile.String())
- fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=",
- strings.Join(a.exportedProguardFlagFiles.Strings(), " "))
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.exportPackage)
+ entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", a.extraAaptPackagesFile)
+ entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile)
+ entries.AddStrings("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.exportedProguardFlagFiles.Strings()...)
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
})
- return data
+ return entries
}
-func (jd *Javadoc) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
+func (jd *Javadoc) AndroidMkEntries() android.AndroidMkEntries {
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(jd.stubsSrcJar),
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
if BoolDefault(jd.properties.Installable, true) {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_DOC_ZIP := ", jd.docZip.String())
+ entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", jd.docZip)
}
if jd.stubsSrcJar != nil {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_STUBS_SRCJAR := ", jd.stubsSrcJar.String())
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", jd.stubsSrcJar)
}
},
},
}
}
-func (ddoc *Droiddoc) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
+func (ddoc *Droiddoc) AndroidMkEntries() android.AndroidMkEntries {
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(ddoc.stubsSrcJar),
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
if BoolDefault(ddoc.Javadoc.properties.Installable, true) && ddoc.Javadoc.docZip != nil {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_DOC_ZIP := ", ddoc.Javadoc.docZip.String())
+ entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", ddoc.Javadoc.docZip)
}
if ddoc.Javadoc.stubsSrcJar != nil {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_STUBS_SRCJAR := ", ddoc.Javadoc.stubsSrcJar.String())
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", ddoc.Javadoc.stubsSrcJar)
}
+ apiFilePrefix := "INTERNAL_PLATFORM_"
+ if String(ddoc.properties.Api_tag_name) != "" {
+ apiFilePrefix += String(ddoc.properties.Api_tag_name) + "_"
+ }
+ if ddoc.apiFile != nil {
+ entries.SetPath(apiFilePrefix+"API_FILE", ddoc.apiFile)
+ }
+ if ddoc.dexApiFile != nil {
+ entries.SetPath(apiFilePrefix+"DEX_API_FILE", ddoc.dexApiFile)
+ }
+ if ddoc.privateApiFile != nil {
+ entries.SetPath(apiFilePrefix+"PRIVATE_API_FILE", ddoc.privateApiFile)
+ }
+ if ddoc.privateDexApiFile != nil {
+ entries.SetPath(apiFilePrefix+"PRIVATE_DEX_API_FILE", ddoc.privateDexApiFile)
+ }
+ if ddoc.removedApiFile != nil {
+ entries.SetPath(apiFilePrefix+"REMOVED_API_FILE", ddoc.removedApiFile)
+ }
+ if ddoc.removedDexApiFile != nil {
+ entries.SetPath(apiFilePrefix+"REMOVED_DEX_API_FILE", ddoc.removedDexApiFile)
+ }
+ if ddoc.exactApiFile != nil {
+ entries.SetPath(apiFilePrefix+"EXACT_API_FILE", ddoc.exactApiFile)
+ }
+ if ddoc.proguardFile != nil {
+ entries.SetPath(apiFilePrefix+"PROGUARD_FILE", ddoc.proguardFile)
+ }
+ },
+ },
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
if ddoc.checkCurrentApiTimestamp != nil {
fmt.Fprintln(w, ".PHONY:", ddoc.Name()+"-check-current-api")
fmt.Fprintln(w, ddoc.Name()+"-check-current-api:",
@@ -493,58 +510,59 @@
fmt.Fprintln(w, "droidcore: checkapi")
}
}
- apiFilePrefix := "INTERNAL_PLATFORM_"
- if String(ddoc.properties.Api_tag_name) != "" {
- apiFilePrefix += String(ddoc.properties.Api_tag_name) + "_"
- }
- if ddoc.apiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"API_FILE := ", ddoc.apiFile.String())
- }
- if ddoc.dexApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"DEX_API_FILE := ", ddoc.dexApiFile.String())
- }
- if ddoc.privateApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"PRIVATE_API_FILE := ", ddoc.privateApiFile.String())
- }
- if ddoc.privateDexApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"PRIVATE_DEX_API_FILE := ", ddoc.privateDexApiFile.String())
- }
- if ddoc.removedApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"REMOVED_API_FILE := ", ddoc.removedApiFile.String())
- }
- if ddoc.removedDexApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"REMOVED_DEX_API_FILE := ", ddoc.removedDexApiFile.String())
- }
- if ddoc.exactApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"EXACT_API_FILE := ", ddoc.exactApiFile.String())
- }
- if ddoc.proguardFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"PROGUARD_FILE := ", ddoc.proguardFile.String())
- }
},
},
}
}
-func (dstubs *Droidstubs) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
+func (dstubs *Droidstubs) AndroidMkEntries() android.AndroidMkEntries {
+ return android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(dstubs.stubsSrcJar),
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
if dstubs.Javadoc.stubsSrcJar != nil {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_STUBS_SRCJAR := ", dstubs.Javadoc.stubsSrcJar.String())
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.stubsSrcJar)
}
if dstubs.apiVersionsXml != nil {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_API_VERSIONS_XML := ", dstubs.apiVersionsXml.String())
+ entries.SetPath("LOCAL_DROIDDOC_API_VERSIONS_XML", dstubs.apiVersionsXml)
}
if dstubs.annotationsZip != nil {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_ANNOTATIONS_ZIP := ", dstubs.annotationsZip.String())
+ entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.annotationsZip)
}
if dstubs.jdiffDocZip != nil {
- fmt.Fprintln(w, "LOCAL_DROIDDOC_JDIFF_DOC_ZIP := ", dstubs.jdiffDocZip.String())
+ entries.SetPath("LOCAL_DROIDDOC_JDIFF_DOC_ZIP", dstubs.jdiffDocZip)
}
+ apiFilePrefix := "INTERNAL_PLATFORM_"
+ if String(dstubs.properties.Api_tag_name) != "" {
+ apiFilePrefix += String(dstubs.properties.Api_tag_name) + "_"
+ }
+ if dstubs.apiFile != nil {
+ entries.SetPath(apiFilePrefix+"API_FILE", dstubs.apiFile)
+ }
+ if dstubs.dexApiFile != nil {
+ entries.SetPath(apiFilePrefix+"DEX_API_FILE", dstubs.dexApiFile)
+ }
+ if dstubs.privateApiFile != nil {
+ entries.SetPath(apiFilePrefix+"PRIVATE_API_FILE", dstubs.privateApiFile)
+ }
+ if dstubs.privateDexApiFile != nil {
+ entries.SetPath(apiFilePrefix+"PRIVATE_DEX_API_FILE", dstubs.privateDexApiFile)
+ }
+ if dstubs.removedApiFile != nil {
+ entries.SetPath(apiFilePrefix+"REMOVED_API_FILE", dstubs.removedApiFile)
+ }
+ if dstubs.removedDexApiFile != nil {
+ entries.SetPath(apiFilePrefix+"REMOVED_DEX_API_FILE", dstubs.removedDexApiFile)
+ }
+ if dstubs.exactApiFile != nil {
+ entries.SetPath(apiFilePrefix+"EXACT_API_FILE", dstubs.exactApiFile)
+ }
+ },
+ },
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
if dstubs.checkCurrentApiTimestamp != nil {
fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-current-api")
fmt.Fprintln(w, dstubs.Name()+"-check-current-api:",
@@ -588,31 +606,6 @@
fmt.Fprintln(w, ".PHONY:", "droidcore")
fmt.Fprintln(w, "droidcore: ", dstubs.Name()+"-check-nullability-warnings")
}
- apiFilePrefix := "INTERNAL_PLATFORM_"
- if String(dstubs.properties.Api_tag_name) != "" {
- apiFilePrefix += String(dstubs.properties.Api_tag_name) + "_"
- }
- if dstubs.apiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"API_FILE := ", dstubs.apiFile.String())
- }
- if dstubs.dexApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"DEX_API_FILE := ", dstubs.dexApiFile.String())
- }
- if dstubs.privateApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"PRIVATE_API_FILE := ", dstubs.privateApiFile.String())
- }
- if dstubs.privateDexApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"PRIVATE_DEX_API_FILE := ", dstubs.privateDexApiFile.String())
- }
- if dstubs.removedApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"REMOVED_API_FILE := ", dstubs.removedApiFile.String())
- }
- if dstubs.removedDexApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"REMOVED_DEX_API_FILE := ", dstubs.removedDexApiFile.String())
- }
- if dstubs.exactApiFile != nil {
- fmt.Fprintln(w, apiFilePrefix+"EXACT_API_FILE := ", dstubs.exactApiFile.String())
- }
},
},
}
@@ -627,7 +620,7 @@
func(entries *android.AndroidMkEntries) {
entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", Bool(a.properties.Privileged))
if a.certificate != nil {
- entries.SetString("LOCAL_CERTIFICATE", a.certificate.Pem.String())
+ entries.SetPath("LOCAL_CERTIFICATE", a.certificate.Pem)
} else {
entries.SetString("LOCAL_CERTIFICATE", "PRESIGNED")
}
@@ -644,25 +637,13 @@
func (a *AndroidTestImport) AndroidMkEntries() android.AndroidMkEntries {
entries := a.AndroidAppImport.AndroidMkEntries()
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
- testSuiteComponentEntries(entries, a.testProperties.Test_suites)
- androidMkEntriesWriteTestData(a.data, entries)
+ testSuiteComponent(entries, a.testProperties.Test_suites)
+ androidMkWriteTestData(a.data, entries)
})
return entries
}
-func androidMkWriteTestData(data android.Paths, ret *android.AndroidMkData) {
- var testFiles []string
- for _, d := range data {
- testFiles = append(testFiles, d.String()+":"+d.Rel())
- }
- if len(testFiles) > 0 {
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUPPORT_FILES := "+strings.Join(testFiles, " "))
- })
- }
-}
-
-func androidMkEntriesWriteTestData(data android.Paths, entries *android.AndroidMkEntries) {
+func androidMkWriteTestData(data android.Paths, entries *android.AndroidMkEntries) {
var testFiles []string
for _, d := range data {
testFiles = append(testFiles, d.String()+":"+d.Rel())
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index fbf2baa..438b66a 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -15,107 +15,12 @@
package java
import (
- "bytes"
- "io"
- "io/ioutil"
- "strings"
+ "reflect"
"testing"
"android/soong/android"
)
-type testAndroidMk struct {
- *testing.T
- body []byte
-}
-
-type testAndroidMkModule struct {
- *testing.T
- props map[string]string
-}
-
-func newTestAndroidMk(t *testing.T, r io.Reader) *testAndroidMk {
- t.Helper()
- buf, err := ioutil.ReadAll(r)
- if err != nil {
- t.Fatal("failed to open read Android.mk.", err)
- }
- return &testAndroidMk{
- T: t,
- body: buf,
- }
-}
-
-func parseAndroidMkProps(lines []string) map[string]string {
- props := make(map[string]string)
- for _, line := range lines {
- line = strings.TrimLeft(line, " ")
- if line == "" || strings.HasPrefix(line, "#") {
- continue
- }
- tokens := strings.Split(line, " ")
- if tokens[1] == "+=" {
- props[tokens[0]] += " " + strings.Join(tokens[2:], " ")
- } else {
- props[tokens[0]] = strings.Join(tokens[2:], " ")
- }
- }
- return props
-}
-
-func (t *testAndroidMk) moduleFor(moduleName string) *testAndroidMkModule {
- t.Helper()
- lines := strings.Split(string(t.body), "\n")
- index := android.IndexList("LOCAL_MODULE := "+moduleName, lines)
- if index == -1 {
- t.Fatalf("%q is not found.", moduleName)
- }
- lines = lines[index:]
- includeIndex := android.IndexListPred(func(line string) bool {
- return strings.HasPrefix(line, "include")
- }, lines)
- if includeIndex == -1 {
- t.Fatalf("%q is not properly defined. (\"include\" not found).", moduleName)
- }
- props := parseAndroidMkProps(lines[:includeIndex])
- return &testAndroidMkModule{
- T: t.T,
- props: props,
- }
-}
-
-func (t *testAndroidMkModule) hasRequired(dep string) {
- t.Helper()
- required, ok := t.props["LOCAL_REQUIRED_MODULES"]
- if !ok {
- t.Error("LOCAL_REQUIRED_MODULES is not found.")
- return
- }
- if !android.InList(dep, strings.Split(required, " ")) {
- t.Errorf("%q is expected in LOCAL_REQUIRED_MODULES, but not found in %q.", dep, required)
- }
-}
-
-func (t *testAndroidMkModule) hasNoRequired(dep string) {
- t.Helper()
- required, ok := t.props["LOCAL_REQUIRED_MODULES"]
- if !ok {
- return
- }
- if android.InList(dep, strings.Split(required, " ")) {
- t.Errorf("%q is not expected in LOCAL_REQUIRED_MODULES, but found.", dep)
- }
-}
-
-func getAndroidMk(t *testing.T, ctx *android.TestContext, config android.Config, name string) *testAndroidMk {
- t.Helper()
- lib, _ := ctx.ModuleForTests(name, "android_common").Module().(*Library)
- data := android.AndroidMkDataForTest(t, config, "", lib)
- w := &bytes.Buffer{}
- data.Custom(w, name, "", "", data)
- return newTestAndroidMk(t, w)
-}
-
func TestRequired(t *testing.T) {
ctx, config := testJava(t, `
java_library {
@@ -125,8 +30,14 @@
}
`)
- mk := getAndroidMk(t, ctx, config, "foo")
- mk.moduleFor("foo").hasRequired("libfoo")
+ mod := ctx.ModuleForTests("foo", "android_common").Module()
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+
+ expected := []string{"libfoo"}
+ actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual)
+ }
}
func TestHostdex(t *testing.T) {
@@ -138,9 +49,19 @@
}
`)
- mk := getAndroidMk(t, ctx, config, "foo")
- mk.moduleFor("foo")
- mk.moduleFor("foo-hostdex")
+ mod := ctx.ModuleForTests("foo", "android_common").Module()
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+
+ expected := []string{"foo"}
+ actual := entries.EntryMap["LOCAL_MODULE"]
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Unexpected module name - expected: %q, actual: %q", expected, actual)
+ }
+
+ footerLines := entries.FooterLinesForTests()
+ if !android.InList("LOCAL_MODULE := foo-hostdex", footerLines) {
+ t.Errorf("foo-hostdex is not found in the footers: %q", footerLines)
+ }
}
func TestHostdexRequired(t *testing.T) {
@@ -153,9 +74,19 @@
}
`)
- mk := getAndroidMk(t, ctx, config, "foo")
- mk.moduleFor("foo").hasRequired("libfoo")
- mk.moduleFor("foo-hostdex").hasRequired("libfoo")
+ mod := ctx.ModuleForTests("foo", "android_common").Module()
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+
+ expected := []string{"libfoo"}
+ actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual)
+ }
+
+ footerLines := entries.FooterLinesForTests()
+ if !android.InList("LOCAL_REQUIRED_MODULES := libfoo", footerLines) {
+ t.Errorf("Wrong or missing required line for foo-hostdex in the footers: %q", footerLines)
+ }
}
func TestHostdexSpecificRequired(t *testing.T) {
@@ -172,7 +103,15 @@
}
`)
- mk := getAndroidMk(t, ctx, config, "foo")
- mk.moduleFor("foo").hasNoRequired("libfoo")
- mk.moduleFor("foo-hostdex").hasRequired("libfoo")
+ mod := ctx.ModuleForTests("foo", "android_common").Module()
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+
+ if r, ok := entries.EntryMap["LOCAL_REQUIRED_MODULES"]; ok {
+ t.Errorf("Unexpected required modules: %q", r)
+ }
+
+ footerLines := entries.FooterLinesForTests()
+ if !android.InList("LOCAL_REQUIRED_MODULES += libfoo", footerLines) {
+ t.Errorf("Wrong or missing required line for foo-hostdex in the footers: %q", footerLines)
+ }
}
diff --git a/java/app.go b/java/app.go
index d00c4c0..3ee8b8d 100644
--- a/java/app.go
+++ b/java/app.go
@@ -126,6 +126,10 @@
// the install APK name is normally the same as the module name, but can be overridden with PRODUCT_PACKAGE_NAME_OVERRIDES.
installApkName string
+ installDir android.OutputPath
+
+ onDeviceDir string
+
additionalAaptFlags []string
noticeOutputs android.NoticeOutputs
@@ -319,7 +323,6 @@
} else {
installDir = filepath.Join("app", a.installApkName)
}
-
a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
a.dexpreopter.isInstallable = Bool(a.properties.Installable)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
@@ -352,7 +355,7 @@
return jniJarFile
}
-func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) {
+func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext) {
// Collect NOTICE files from all dependencies.
seenModules := make(map[android.Module]bool)
noticePathSet := make(map[android.Path]bool)
@@ -392,7 +395,7 @@
return noticePaths[i].String() < noticePaths[j].String()
})
- a.noticeOutputs = android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
+ a.noticeOutputs = android.BuildNoticeOutput(ctx, a.installDir, a.installApkName+".apk", noticePaths)
}
// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
@@ -438,17 +441,19 @@
// Check if the install APK name needs to be overridden.
a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
- var installDir android.OutputPath
if ctx.ModuleName() == "framework-res" {
// framework-res.apk is installed as system/framework/framework-res.apk
- installDir = android.PathForModuleInstall(ctx, "framework")
+ a.installDir = android.PathForModuleInstall(ctx, "framework")
} else if Bool(a.appProperties.Privileged) {
- installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
+ a.installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
+ } else if ctx.InstallInTestcases() {
+ a.installDir = android.PathForModuleInstall(ctx, a.installApkName)
} else {
- installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
+ a.installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
}
+ a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
- a.noticeBuildActions(ctx, installDir)
+ a.noticeBuildActions(ctx)
if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
a.aapt.noticeFile = a.noticeOutputs.HtmlGzOutput
}
@@ -494,9 +499,9 @@
a.bundleFile = bundleFile
// Install the app package.
- ctx.InstallFile(installDir, a.installApkName+".apk", a.outputFile)
+ ctx.InstallFile(a.installDir, a.installApkName+".apk", a.outputFile)
for _, split := range a.aapt.splits {
- ctx.InstallFile(installDir, a.installApkName+"_"+split.suffix+".apk", split.path)
+ ctx.InstallFile(a.installDir, a.installApkName+"_"+split.suffix+".apk", split.path)
}
}
@@ -598,6 +603,10 @@
data android.Paths
}
+func (a *AndroidTest) InstallInTestcases() bool {
+ return true
+}
+
func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Check if the instrumentation target package is overridden before generating build actions.
if a.appTestProperties.Instrumentation_for != nil {
@@ -608,7 +617,8 @@
}
a.generateAndroidBuildActions(ctx)
- a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites)
+ a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config,
+ a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
}
@@ -656,6 +666,11 @@
// list of compatibility suites (for example "cts", "vts") that the module should be
// installed into.
Test_suites []string `android:"arch_variant"`
+
+ // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+ // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+ // explicitly.
+ Auto_gen_config *bool
}
type AndroidTestHelperApp struct {
diff --git a/java/builder.go b/java/builder.go
index 9e068fa..0a5c79b 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -64,6 +64,7 @@
_ = pctx.VariableFunc("kytheCorpus",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
+ _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
// Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about
// "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
// to field java.nio.Buffer.address"
@@ -74,6 +75,7 @@
`( [ ! -s $srcJarDir/list -a ! -s $out.rsp ] || ` +
`KYTHE_ROOT_DIRECTORY=. KYTHE_OUTPUT_FILE=$out ` +
`KYTHE_CORPUS=${kytheCorpus} ` +
+ `KYTHE_VNAMES=${kytheVnames} ` +
`${config.SoongJavacWrapper} ${config.JavaCmd} ` +
`--add-opens=java.base/java.nio=ALL-UNNAMED ` +
`-jar ${config.JavaKytheExtractorJar} ` +
@@ -84,6 +86,7 @@
CommandDeps: []string{
"${config.JavaCmd}",
"${config.JavaKytheExtractorJar}",
+ "${kytheVnames}",
"${config.ZipSyncCmd}",
},
CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 5deac5e..1d5331e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -57,6 +57,10 @@
// filegroup or genrule can be included within this property.
Exclude_srcs []string `android:"path,arch_variant"`
+ // list of package names that should actually be used. If this property is left unspecified,
+ // all the sources from the srcs property is used.
+ Filter_packages []string
+
// list of java libraries that will be in the classpath.
Libs []string `android:"arch_variant"`
@@ -524,6 +528,34 @@
// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
// may contain filegroup or genrule.
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+
+ filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path {
+ if filterPackages == nil {
+ return srcs
+ }
+ filtered := []android.Path{}
+ for _, src := range srcs {
+ if src.Ext() != ".java" {
+ // Don't filter-out non-Java (=generated sources) by package names. This is not ideal,
+ // but otherwise metalava emits stub sources having references to the generated AIDL classes
+ // in filtered-out pacages (e.g. com.android.internal.*).
+ // TODO(b/141149570) We need to fix this by introducing default private constructors or
+ // fixing metalava to not emit constructors having references to unknown classes.
+ filtered = append(filtered, src)
+ continue
+ }
+ packageName := strings.ReplaceAll(filepath.Dir(src.Rel()), "/", ".")
+ for _, pkg := range filterPackages {
+ if strings.HasPrefix(packageName, pkg) {
+ filtered = append(filtered, src)
+ break
+ }
+ }
+ }
+ return filtered
+ }
+ srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)
+
flags := j.collectAidlFlags(ctx, deps)
srcFiles = j.genSources(ctx, srcFiles, flags)
diff --git a/java/gen.go b/java/gen.go
index a69e9a2..b840b60 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -23,7 +23,6 @@
)
func init() {
- pctx.HostBinToolVariable("syspropCmd", "sysprop_java")
pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py")
pctx.SourcePathVariable("mergeLogtagsCmd", "build/make/tools/merge-event-log-tags.py")
pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py")
@@ -48,17 +47,6 @@
Command: "$mergeLogtagsCmd -o $out $in",
CommandDeps: []string{"$mergeLogtagsCmd", "$logtagsLib"},
})
-
- sysprop = pctx.AndroidStaticRule("sysprop",
- blueprint.RuleParams{
- Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
- `$syspropCmd --scope $scope --java-output-dir $out.tmp $in && ` +
- `${config.SoongZipCmd} -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
- CommandDeps: []string{
- "$syspropCmd",
- "${config.SoongZipCmd}",
- },
- }, "scope")
)
func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path {
@@ -93,22 +81,6 @@
return javaFile
}
-func genSysprop(ctx android.ModuleContext, syspropFile android.Path, scope string) android.Path {
- srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
-
- ctx.Build(pctx, android.BuildParams{
- Rule: sysprop,
- Description: "sysprop_java " + syspropFile.Rel(),
- Output: srcJarFile,
- Input: syspropFile,
- Args: map[string]string{
- "scope": scope,
- },
- })
-
- return srcJarFile
-}
-
func genAidlIncludeFlags(srcFiles android.Paths) string {
var baseDirs []string
for _, srcFile := range srcFiles {
@@ -141,29 +113,6 @@
case ".proto":
srcJarFile := genProto(ctx, srcFile, flags.proto)
outSrcFiles = append(outSrcFiles, srcJarFile)
- case ".sysprop":
- // internal scope contains all properties
- // public scope only contains public properties
- // use public if the owner is different from client
- scope := "internal"
- if j.properties.Sysprop.Platform != nil {
- isProduct := ctx.ProductSpecific()
- isVendor := ctx.SocSpecific()
- isOwnerPlatform := Bool(j.properties.Sysprop.Platform)
-
- if isProduct {
- // product can't own any sysprop_library now, so product must use public scope
- scope = "public"
- } else if isVendor && !isOwnerPlatform {
- // vendor and odm can't use system's internal property.
- scope = "public"
- }
-
- // We don't care about clients under system.
- // They can't use sysprop_library owned by other partitions.
- }
- srcJarFile := genSysprop(ctx, srcFile, scope)
- outSrcFiles = append(outSrcFiles, srcJarFile)
default:
outSrcFiles = append(outSrcFiles, srcFile)
}
diff --git a/java/java.go b/java/java.go
index b05d7bb..f7b0f53 100644
--- a/java/java.go
+++ b/java/java.go
@@ -184,10 +184,6 @@
Output_params []string
}
- Sysprop struct {
- Platform *bool
- } `blueprint:"mutated"`
-
Instrument bool `blueprint:"mutated"`
// List of files to include in the META-INF/services folder of the resulting jar.
@@ -290,6 +286,7 @@
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
+ android.SdkBase
properties CompilerProperties
protoProperties android.ProtoProperties
@@ -398,6 +395,7 @@
AidlIncludeDirs() android.Paths
ExportedSdkLibs() []string
SrcJarArgs() ([]string, android.Paths)
+ BaseModuleName() string
}
type SdkLibraryDependency interface {
@@ -534,7 +532,9 @@
ctx.PropertyErrorf("sdk_version",
`system_modules is required to be set when sdk_version is "none", did you mean "core_platform"`)
} else if *j.deviceProperties.System_modules != "none" {
+ // Add the system modules to both the system modules and bootclasspath.
ctx.AddVariationDependencies(nil, systemModulesTag, *j.deviceProperties.System_modules)
+ ctx.AddVariationDependencies(nil, bootClasspathTag, *j.deviceProperties.System_modules)
}
if ctx.ModuleName() == "android_stubs_current" ||
ctx.ModuleName() == "android_system_stubs_current" ||
@@ -580,18 +580,6 @@
return false
}
-func shardPaths(paths android.Paths, shardSize int) []android.Paths {
- ret := make([]android.Paths, 0, (len(paths)+shardSize-1)/shardSize)
- for len(paths) > shardSize {
- ret = append(ret, paths[0:shardSize])
- paths = paths[shardSize:]
- }
- if len(paths) > 0 {
- ret = append(ret, paths)
- }
- return ret
-}
-
func (j *Module) hasSrcExt(ext string) bool {
return hasSrcExt(j.properties.Srcs, ext)
}
@@ -847,6 +835,12 @@
}
default:
switch tag {
+ case bootClasspathTag:
+ // If a system modules dependency has been added to the bootclasspath
+ // then add its libs to the bootclasspath.
+ sm := module.(*SystemModules)
+ deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...)
+
case systemModulesTag:
if deps.systemModules != nil {
panic("Found two system module dependencies")
@@ -1150,7 +1144,7 @@
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
if len(uniqueSrcFiles) > 0 {
- shardSrcs = shardPaths(uniqueSrcFiles, shardSize)
+ shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize)
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
nil, flags, extraJarDeps)
@@ -1632,6 +1626,7 @@
InitJavaModule(module, android.HostAndDeviceSupported)
android.InitApexModule(module)
+ android.InitSdkAwareModule(module)
return module
}
@@ -1678,6 +1673,11 @@
// list of files or filegroup modules that provide data that should be installed alongside
// the test
Data []string `android:"path"`
+
+ // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+ // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+ // explicitly.
+ Auto_gen_config *bool
}
type testHelperLibraryProperties struct {
@@ -1702,7 +1702,8 @@
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template, j.testProperties.Test_suites)
+ j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
+ j.testProperties.Test_suites, j.testProperties.Auto_gen_config)
j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
j.Library.GenerateAndroidBuildActions(ctx)
@@ -1912,6 +1913,7 @@
android.DefaultableModuleBase
android.ApexModuleBase
prebuilt android.Prebuilt
+ android.SdkBase
properties ImportProperties
@@ -2068,6 +2070,7 @@
android.InitPrebuiltModule(module, &module.properties.Jars)
InitJavaModule(module, android.HostAndDeviceSupported)
android.InitApexModule(module)
+ android.InitSdkAwareModule(module)
return module
}
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index c370811..0d5e31f 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -82,7 +82,7 @@
props.Sdk_version = proptools.StringPtr("current")
props.Installable = proptools.BoolPtr(false)
- mctx.CreateModule(android.ModuleFactoryAdaptor(ImportFactory), &props)
+ mctx.CreateModule(ImportFactory, &props)
}
func createFilegroup(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
@@ -93,7 +93,7 @@
}{}
filegroupProps.Name = proptools.StringPtr(fgName)
filegroupProps.Srcs = []string{path}
- mctx.CreateModule(android.ModuleFactoryAdaptor(android.FileGroupFactory), &filegroupProps)
+ mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
}
func getPrebuiltFiles(mctx android.TopDownMutatorContext, name string) []string {
diff --git a/java/robolectric.go b/java/robolectric.go
index cbe3557..b7646eb 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -105,7 +105,7 @@
r.roboSrcJar = roboSrcJar
for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
- r.libs = append(r.libs, ctx.OtherModuleName(dep))
+ r.libs = append(r.libs, dep.(Dependency).BaseModuleName())
}
// TODO: this could all be removed if tradefed was used as the test runner, it will find everything
@@ -123,25 +123,6 @@
}
}
-func shardTests(paths []string, shards int) [][]string {
- if shards > len(paths) {
- shards = len(paths)
- }
- if shards == 0 {
- return nil
- }
- ret := make([][]string, 0, shards)
- shardSize := (len(paths) + shards - 1) / shards
- for len(paths) > shardSize {
- ret = append(ret, paths[0:shardSize])
- paths = paths[shardSize:]
- }
- if len(paths) > 0 {
- ret = append(ret, paths)
- }
- return ret
-}
-
func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath, instrumentedApp *AndroidApp) {
manifest := instrumentedApp.mergedManifestFile
resourceApk := instrumentedApp.outputFile
@@ -177,32 +158,34 @@
TransformResourcesToJar(ctx, outputFile, srcJarArgs, srcJarDeps)
}
-func (r *robolectricTest) AndroidMk() android.AndroidMkData {
- data := r.Library.AndroidMk()
+func (r *robolectricTest) AndroidMkEntries() android.AndroidMkEntries {
+ entries := r.Library.AndroidMkEntries()
- data.Custom = func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- android.WriteAndroidMkData(w, data)
+ entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ if s := r.robolectricProperties.Test_options.Shards; s != nil && *s > 1 {
+ numShards := int(*s)
+ shardSize := (len(r.tests) + numShards - 1) / numShards
+ shards := android.ShardStrings(r.tests, shardSize)
+ for i, shard := range shards {
+ r.writeTestRunner(w, name, "Run"+name+strconv.Itoa(i), shard)
+ }
- if s := r.robolectricProperties.Test_options.Shards; s != nil && *s > 1 {
- shards := shardTests(r.tests, int(*s))
- for i, shard := range shards {
- r.writeTestRunner(w, name, "Run"+name+strconv.Itoa(i), shard)
+ // TODO: add rules to dist the outputs of the individual tests, or combine them together?
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, ".PHONY:", "Run"+name)
+ fmt.Fprintln(w, "Run"+name, ": \\")
+ for i := range shards {
+ fmt.Fprintln(w, " ", "Run"+name+strconv.Itoa(i), "\\")
+ }
+ fmt.Fprintln(w, "")
+ } else {
+ r.writeTestRunner(w, name, "Run"+name, r.tests)
}
-
- // TODO: add rules to dist the outputs of the individual tests, or combine them together?
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, ".PHONY:", "Run"+name)
- fmt.Fprintln(w, "Run"+name, ": \\")
- for i := range shards {
- fmt.Fprintln(w, " ", "Run"+name+strconv.Itoa(i), "\\")
- }
- fmt.Fprintln(w, "")
- } else {
- r.writeTestRunner(w, name, "Run"+name, r.tests)
- }
+ },
}
- return data
+ return entries
}
func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, tests []string) {
@@ -233,6 +216,7 @@
module.AddProperties(
&module.Module.properties,
+ &module.Module.deviceProperties,
&module.Module.protoProperties,
&module.robolectricProperties)
diff --git a/java/robolectric_test.go b/java/robolectric_test.go
deleted file mode 100644
index e89c6e7..0000000
--- a/java/robolectric_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-import (
- "reflect"
- "testing"
-)
-
-func Test_shardTests(t *testing.T) {
- type args struct {
- paths []string
- shards int
- }
- tests := []struct {
- name string
- args args
- want [][]string
- }{
- {
- name: "empty",
- args: args{
- paths: nil,
- shards: 1,
- },
- want: [][]string(nil),
- },
- {
- name: "too many shards",
- args: args{
- paths: []string{"a", "b"},
- shards: 3,
- },
- want: [][]string{{"a"}, {"b"}},
- },
- {
- name: "single shard",
- args: args{
- paths: []string{"a", "b"},
- shards: 1,
- },
- want: [][]string{{"a", "b"}},
- },
- {
- name: "shard per input",
- args: args{
- paths: []string{"a", "b", "c"},
- shards: 3,
- },
- want: [][]string{{"a"}, {"b"}, {"c"}},
- },
- {
- name: "balanced shards",
- args: args{
- paths: []string{"a", "b", "c", "d"},
- shards: 2,
- },
- want: [][]string{{"a", "b"}, {"c", "d"}},
- },
- {
- name: "unbalanced shards",
- args: args{
- paths: []string{"a", "b", "c"},
- shards: 2,
- },
- want: [][]string{{"a", "b"}, {"c"}},
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if got := shardTests(tt.args.paths, tt.args.shards); !reflect.DeepEqual(got, tt.want) {
- t.Errorf("shardTests() = %v, want %v", got, tt.want)
- }
- })
- }
-}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 30fd1c4..476e549 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -197,65 +197,65 @@
})
}
-func (module *SdkLibrary) AndroidMk() android.AndroidMkData {
- data := module.Library.AndroidMk()
- data.Required = append(data.Required, module.xmlFileName())
+func (module *SdkLibrary) AndroidMkEntries() android.AndroidMkEntries {
+ entries := module.Library.AndroidMkEntries()
+ entries.Required = append(entries.Required, module.xmlFileName())
- data.Custom = func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- android.WriteAndroidMkData(w, data)
-
- module.Library.AndroidMkHostDex(w, name, data)
- if !Bool(module.sdkLibraryProperties.No_dist) {
- // Create a phony module that installs the impl library, for the case when this lib is
- // in PRODUCT_PACKAGES.
- owner := module.ModuleBase.Owner()
- if owner == "" {
- if Bool(module.sdkLibraryProperties.Core_lib) {
- owner = "core"
- } else {
- owner = "android"
+ entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ module.Library.AndroidMkHostDex(w, name, entries)
+ if !Bool(module.sdkLibraryProperties.No_dist) {
+ // Create a phony module that installs the impl library, for the case when this lib is
+ // in PRODUCT_PACKAGES.
+ owner := module.ModuleBase.Owner()
+ if owner == "" {
+ if Bool(module.sdkLibraryProperties.Core_lib) {
+ owner = "core"
+ } else {
+ owner = "android"
+ }
+ }
+ // Create dist rules to install the stubs libs to the dist dir
+ if len(module.publicApiStubsPath) == 1 {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ module.publicApiStubsImplPath.Strings()[0]+
+ ":"+path.Join("apistubs", owner, "public",
+ module.BaseModuleName()+".jar")+")")
+ }
+ if len(module.systemApiStubsPath) == 1 {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ module.systemApiStubsImplPath.Strings()[0]+
+ ":"+path.Join("apistubs", owner, "system",
+ module.BaseModuleName()+".jar")+")")
+ }
+ if len(module.testApiStubsPath) == 1 {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ module.testApiStubsImplPath.Strings()[0]+
+ ":"+path.Join("apistubs", owner, "test",
+ module.BaseModuleName()+".jar")+")")
+ }
+ if module.publicApiFilePath != nil {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ module.publicApiFilePath.String()+
+ ":"+path.Join("apistubs", owner, "public", "api",
+ module.BaseModuleName()+".txt")+")")
+ }
+ if module.systemApiFilePath != nil {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ module.systemApiFilePath.String()+
+ ":"+path.Join("apistubs", owner, "system", "api",
+ module.BaseModuleName()+".txt")+")")
+ }
+ if module.testApiFilePath != nil {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ module.testApiFilePath.String()+
+ ":"+path.Join("apistubs", owner, "test", "api",
+ module.BaseModuleName()+".txt")+")")
}
}
- // Create dist rules to install the stubs libs to the dist dir
- if len(module.publicApiStubsPath) == 1 {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.publicApiStubsImplPath.Strings()[0]+
- ":"+path.Join("apistubs", owner, "public",
- module.BaseModuleName()+".jar")+")")
- }
- if len(module.systemApiStubsPath) == 1 {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.systemApiStubsImplPath.Strings()[0]+
- ":"+path.Join("apistubs", owner, "system",
- module.BaseModuleName()+".jar")+")")
- }
- if len(module.testApiStubsPath) == 1 {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.testApiStubsImplPath.Strings()[0]+
- ":"+path.Join("apistubs", owner, "test",
- module.BaseModuleName()+".jar")+")")
- }
- if module.publicApiFilePath != nil {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.publicApiFilePath.String()+
- ":"+path.Join("apistubs", owner, "public", "api",
- module.BaseModuleName()+".txt")+")")
- }
- if module.systemApiFilePath != nil {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.systemApiFilePath.String()+
- ":"+path.Join("apistubs", owner, "system", "api",
- module.BaseModuleName()+".txt")+")")
- }
- if module.testApiFilePath != nil {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.testApiFilePath.String()+
- ":"+path.Join("apistubs", owner, "test", "api",
- module.BaseModuleName()+".txt")+")")
- }
- }
+ },
}
- return data
+ return entries
}
// Module name of the stubs library
@@ -422,7 +422,7 @@
props.Product_specific = proptools.BoolPtr(true)
}
- mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), &props)
+ mctx.CreateModule(LibraryFactory, &props)
}
// Creates a droiddoc module that creates stubs source files from the given full source
@@ -522,7 +522,7 @@
module.latestRemovedApiFilegroupName(apiScope))
props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true)
- mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
+ mctx.CreateModule(DroidstubsFactory, &props)
}
// Creates the xml file that publicizes the runtime library
@@ -560,7 +560,7 @@
genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
genruleProps.Out = []string{module.xmlFileName()}
- mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps)
+ mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
// creates a prebuilt_etc module to actually place the xml file under
// <partition>/etc/permissions
@@ -582,7 +582,7 @@
} else if module.ProductSpecific() {
etcProps.Product_specific = proptools.BoolPtr(true)
}
- mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
+ mctx.CreateModule(android.PrebuiltEtcFactory, &etcProps)
}
func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
@@ -815,7 +815,7 @@
props.Product_specific = proptools.BoolPtr(true)
}
- mctx.CreateModule(android.ModuleFactoryAdaptor(ImportFactory), &props, &module.properties)
+ mctx.CreateModule(ImportFactory, &props, &module.properties)
javaSdkLibraries := javaSdkLibraries(mctx.Config())
javaSdkLibrariesLock.Lock()
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 6be17eb..88e21d7 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -124,7 +124,7 @@
name: "nostdlib system_modules",
properties: `sdk_version: "none", system_modules: "core-platform-api-stubs-system-modules"`,
system: "core-platform-api-stubs-system-modules",
- bootclasspath: []string{`""`},
+ bootclasspath: []string{"core-platform-api-stubs-system-modules-lib"},
classpath: []string{},
},
{
diff --git a/java/system_modules.go b/java/system_modules.go
index c616249..43e4e11 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -101,6 +101,9 @@
properties SystemModulesProperties
+ // The aggregated header jars from all jars specified in the libs property.
+ // Used when system module is added as a dependency to bootclasspath.
+ headerJars android.Paths
outputDir android.Path
outputDeps android.Paths
}
@@ -118,6 +121,8 @@
jars = append(jars, dep.HeaderJars()...)
})
+ system.headerJars = jars
+
system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, "java.base", jars)
}
diff --git a/java/testing.go b/java/testing.go
index a37c0a9..acbefb9 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -103,7 +103,6 @@
`
systemModules := []string{
- "core-system-modules",
"core-current-stubs-system-modules",
"core-platform-api-stubs-system-modules",
"android_stubs_current_system_modules",
@@ -114,7 +113,13 @@
for _, extra := range systemModules {
bp += fmt.Sprintf(`
java_system_modules {
- name: "%s",
+ name: "%[1]s",
+ libs: ["%[1]s-lib"],
+ }
+ java_library {
+ name: "%[1]s-lib",
+ sdk_version: "none",
+ system_modules: "none",
}
`, extra)
}
diff --git a/python/binary.go b/python/binary.go
index 140f07a..695fa12 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -47,6 +47,11 @@
// false it will act much like the normal `python` executable, but with the sources and
// libraries automatically included in the PYTHONPATH.
Autorun *bool `android:"arch_variant"`
+
+ // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+ // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+ // explicitly.
+ Auto_gen_config *bool
}
type binaryDecorator struct {
diff --git a/python/test.go b/python/test.go
index 55b0ab5..f684fd5 100644
--- a/python/test.go
+++ b/python/test.go
@@ -50,7 +50,8 @@
func (test *testDecorator) install(ctx android.ModuleContext, file android.Path) {
test.testConfig = tradefed.AutoGenPythonBinaryHostTestConfig(ctx, test.testProperties.Test_config,
- test.testProperties.Test_config_template, test.binaryDecorator.binaryProperties.Test_suites)
+ test.testProperties.Test_config_template, test.binaryDecorator.binaryProperties.Test_suites,
+ test.binaryDecorator.binaryProperties.Auto_gen_config)
test.binaryDecorator.pythonInstaller.dir = "nativetest"
test.binaryDecorator.pythonInstaller.dir64 = "nativetest64"
diff --git a/rust/binary.go b/rust/binary.go
index 279c6f5..52f840e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -71,6 +71,15 @@
func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = binary.baseCompiler.compilerFlags(ctx, flags)
+
+ if ctx.toolchain().Bionic() {
+ // no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined, but we can apply this to binaries.
+ flags.LinkFlags = append(flags.LinkFlags,
+ "-Wl,--gc-sections",
+ "-Wl,-z,nocopyreloc",
+ "-Wl,--no-undefined-version")
+ }
+
if binary.preferDynamic() {
flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
}
@@ -86,6 +95,12 @@
}
}
+ if ctx.toolchain().Bionic() {
+ deps = binary.baseCompiler.bionicDeps(ctx, deps)
+ deps.CrtBegin = "crtbegin_dynamic"
+ deps.CrtEnd = "crtend_android"
+ }
+
return deps
}
diff --git a/rust/builder.go b/rust/builder.go
index 64e387b..104313f 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -28,14 +28,13 @@
blueprint.RuleParams{
Command: "$rustcCmd " +
"-C linker=${config.RustLinker} " +
- "-C link-args=\"${config.RustLinkerArgs} ${linkFlags}\" " +
- "-o $out $in ${libFlags} $rustcFlags " +
- "&& $rustcCmd --emit=dep-info -o $out.d $in ${libFlags} $rustcFlags",
+ "-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
+ "--emit link -o $out --emit dep-info=$out.d $in ${libFlags} $rustcFlags",
CommandDeps: []string{"$rustcCmd"},
Depfile: "$out.d",
Deps: blueprint.DepsGCC, // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
},
- "rustcFlags", "linkFlags", "libFlags")
+ "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
)
func init() {
@@ -43,28 +42,19 @@
}
func TransformSrcToBinary(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
- targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
- transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "bin", includeDirs, targetTriple)
+ transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "bin", includeDirs)
}
func TransformSrctoRlib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
- targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
- transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "rlib", includeDirs, targetTriple)
+ transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "rlib", includeDirs)
}
func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
- targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
- transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "dylib", includeDirs, targetTriple)
+ transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "dylib", includeDirs)
}
func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
- // Proc macros are compiler plugins, and thus should target the host compiler
- targetTriple := ""
-
- transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "proc-macro", includeDirs, targetTriple)
+ transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "proc-macro", includeDirs)
}
func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -76,23 +66,28 @@
}
func transformSrctoCrate(ctx android.ModuleContext, main android.Path,
- rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string, targetTriple string) {
+ rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, crtBegin, crtEnd android.OptionalPath, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) {
var inputs android.Paths
var deps android.Paths
- var libFlags, rustcFlags []string
+ var libFlags, rustcFlags, linkFlags []string
crate_name := ctx.(ModuleContext).CrateName()
+ targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
inputs = append(inputs, main)
// Collect rustc flags
- rustcFlags = append(rustcFlags, flags.GlobalFlags...)
+ rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
rustcFlags = append(rustcFlags, flags.RustFlags...)
rustcFlags = append(rustcFlags, "--crate-type="+crate_type)
rustcFlags = append(rustcFlags, "--crate-name="+crate_name)
if targetTriple != "" {
rustcFlags = append(rustcFlags, "--target="+targetTriple)
+ linkFlags = append(linkFlags, "-target "+targetTriple)
}
+ // Collect linker flags
+ linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
+ linkFlags = append(linkFlags, flags.LinkFlags...)
// Collect library/crate flags
for _, lib := range rlibs {
@@ -115,6 +110,9 @@
deps = append(deps, rustLibsToPaths(proc_macros)...)
deps = append(deps, static_libs...)
deps = append(deps, shared_libs...)
+ if crtBegin.Valid() {
+ deps = append(deps, crtBegin.Path(), crtEnd.Path())
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rustc,
@@ -124,8 +122,10 @@
Implicits: deps,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
- "linkFlags": strings.Join(flags.LinkFlags, " "),
+ "linkFlags": strings.Join(linkFlags, " "),
"libFlags": strings.Join(libFlags, " "),
+ "crtBegin": crtBegin.String(),
+ "crtEnd": crtEnd.String(),
},
})
diff --git a/rust/compiler.go b/rust/compiler.go
index 87cf08b..3bfef76 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -25,7 +25,8 @@
func NewBaseCompiler(dir, dir64 string) *baseCompiler {
return &baseCompiler{
Properties: BaseCompilerProperties{
- Edition: &config.DefaultEdition,
+ Edition: &config.DefaultEdition,
+ Deny_warnings: config.DefaultDenyWarnings,
},
dir: dir,
dir64: dir64,
@@ -33,6 +34,9 @@
}
type BaseCompilerProperties struct {
+ // whether to pass "-D warnings" to rustc. Defaults to true.
+ Deny_warnings *bool
+
// flags to pass to rustc
Flags []string `android:"path,arch_variant"`
@@ -109,11 +113,16 @@
func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {
+ if Bool(compiler.Properties.Deny_warnings) {
+ flags.RustFlags = append(flags.RustFlags, "-D warnings")
+ }
flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...)
flags.RustFlags = append(flags.RustFlags, "--edition="+*compiler.Properties.Edition)
flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
- flags.GlobalFlags = append(flags.GlobalFlags, ctx.toolchain().ToolchainRustFlags())
+ flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
+ flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
+ flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
if ctx.Host() && !ctx.Windows() {
rpath_prefix := `\$$ORIGIN/`
@@ -148,6 +157,18 @@
return deps
}
+func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps {
+ deps.SharedLibs = append(deps.SharedLibs, "liblog")
+ deps.SharedLibs = append(deps.SharedLibs, "libc")
+ deps.SharedLibs = append(deps.SharedLibs, "libm")
+ deps.SharedLibs = append(deps.SharedLibs, "libdl")
+
+ //TODO(b/141331117) libstd requires libgcc on Android
+ deps.StaticLibs = append(deps.StaticLibs, "libgcc")
+
+ return deps
+}
+
func (compiler *baseCompiler) crateName() string {
return compiler.Properties.Crate_name
}
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 5369096..bbf9f8d 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -64,7 +64,6 @@
rust_proc_macro {
name: "foo-bar-proc-macro",
srcs: ["foo.rs", "src/bar.rs"],
- host_supported: true,
}`)
// Test prebuilts
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
new file mode 100644
index 0000000..0264052
--- /dev/null
+++ b/rust/config/arm64_device.go
@@ -0,0 +1,92 @@
+// Copyright 2019 The Android Open Source Project
+//
+// 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 config
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ Arm64RustFlags = []string{}
+ Arm64ArchFeatureRustFlags = map[string][]string{}
+ Arm64LinkFlags = []string{
+ "-Wl,--icf=safe",
+ "-Wl,-z,max-page-size=4096",
+
+ "-Wl,-execute-only",
+ }
+
+ Arm64ArchVariantRustFlags = map[string][]string{
+ "armv8-a": []string{},
+ "armv8-2a": []string{},
+ }
+)
+
+func init() {
+ registerToolchainFactory(android.Android, android.Arm64, Arm64ToolchainFactory)
+
+ pctx.StaticVariable("Arm64ToolchainRustFlags", strings.Join(Arm64RustFlags, " "))
+ pctx.StaticVariable("Arm64ToolchainLinkFlags", strings.Join(Arm64LinkFlags, " "))
+
+ for variant, rustFlags := range Arm64ArchVariantRustFlags {
+ pctx.StaticVariable("Arm64"+variant+"VariantRustFlags",
+ strings.Join(rustFlags, " "))
+ }
+
+}
+
+type toolchainArm64 struct {
+ toolchain64Bit
+ toolchainRustFlags string
+}
+
+func (t *toolchainArm64) RustTriple() string {
+ return "aarch64-linux-android"
+}
+
+func (t *toolchainArm64) ToolchainLinkFlags() string {
+ return "${config.DeviceGlobalLinkFlags} ${config.Arm64ToolchainLinkFlags}"
+}
+
+func (t *toolchainArm64) ToolchainRustFlags() string {
+ return t.toolchainRustFlags
+}
+
+func (t *toolchainArm64) RustFlags() string {
+ return "${config.Arm64ToolchainRustFlags}"
+}
+
+func (t *toolchainArm64) Supported() bool {
+ return true
+}
+
+func Arm64ToolchainFactory(arch android.Arch) Toolchain {
+ toolchainRustFlags := []string{
+ "${config.Arm64ToolchainRustFlags}",
+ "${config.Arm64" + arch.ArchVariant + "VariantRustFlags}",
+ }
+
+ toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+ for _, feature := range arch.ArchFeatures {
+ toolchainRustFlags = append(toolchainRustFlags, Arm64ArchFeatureRustFlags[feature]...)
+ }
+
+ return &toolchainArm64{
+ toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+ }
+}
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
new file mode 100644
index 0000000..aedb42b
--- /dev/null
+++ b/rust/config/arm_device.go
@@ -0,0 +1,92 @@
+// Copyright 2019 The Android Open Source Project
+//
+// 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 config
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ ArmRustFlags = []string{}
+ ArmArchFeatureRustFlags = map[string][]string{}
+ ArmLinkFlags = []string{
+ "-Wl,--icf=safe",
+ "-Wl,-m,armelf",
+ }
+
+ ArmArchVariantRustFlags = map[string][]string{
+ "armv7-a": []string{},
+ "armv7-a-neon": []string{},
+ "armv8-a": []string{},
+ "armv8-2a": []string{},
+ }
+)
+
+func init() {
+ registerToolchainFactory(android.Android, android.Arm, ArmToolchainFactory)
+
+ pctx.StaticVariable("ArmToolchainRustFlags", strings.Join(ArmRustFlags, " "))
+ pctx.StaticVariable("ArmToolchainLinkFlags", strings.Join(ArmLinkFlags, " "))
+
+ for variant, rustFlags := range ArmArchVariantRustFlags {
+ pctx.StaticVariable("Arm"+variant+"VariantRustFlags",
+ strings.Join(rustFlags, " "))
+ }
+
+}
+
+type toolchainArm struct {
+ toolchain64Bit
+ toolchainRustFlags string
+}
+
+func (t *toolchainArm) RustTriple() string {
+ return "arm-linux-androideabi"
+}
+
+func (t *toolchainArm) ToolchainLinkFlags() string {
+ return "${config.DeviceGlobalLinkFlags} ${config.ArmToolchainLinkFlags}"
+}
+
+func (t *toolchainArm) ToolchainRustFlags() string {
+ return t.toolchainRustFlags
+}
+
+func (t *toolchainArm) RustFlags() string {
+ return "${config.ArmToolchainRustFlags}"
+}
+
+func (t *toolchainArm) Supported() bool {
+ return true
+}
+
+func ArmToolchainFactory(arch android.Arch) Toolchain {
+ toolchainRustFlags := []string{
+ "${config.ArmToolchainRustFlags}",
+ "${config.Arm" + arch.ArchVariant + "VariantRustFlags}",
+ }
+
+ toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+ for _, feature := range arch.ArchFeatures {
+ toolchainRustFlags = append(toolchainRustFlags, ArmArchFeatureRustFlags[feature]...)
+ }
+
+ return &toolchainArm{
+ toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+ }
+}
diff --git a/rust/config/global.go b/rust/config/global.go
index 7f9f993..ae50804 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -15,6 +15,10 @@
package config
import (
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
_ "android/soong/cc/config"
)
@@ -26,15 +30,33 @@
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
- "libarena",
- "libfmt_macros",
- "libgraphviz",
- "libserialize",
"libstd",
- "libsyntax",
- "libsyntax_ext",
- "libsyntax_pos",
"libterm",
+ "libtest",
+ }
+
+ DefaultDenyWarnings = proptools.BoolPtr(true)
+
+ GlobalRustFlags = []string{
+ "--remap-path-prefix $$(pwd)=",
+ }
+
+ deviceGlobalRustFlags = []string{}
+
+ deviceGlobalLinkFlags = []string{
+ "-Bdynamic",
+ "-nostdlib",
+ "-Wl,-z,noexecstack",
+ "-Wl,-z,relro",
+ "-Wl,-z,now",
+ "-Wl,--build-id=md5",
+ "-Wl,--warn-shared-textrel",
+ "-Wl,--fatal-warnings",
+
+ "-Wl,--pack-dyn-relocs=android+relr",
+ "-Wl,--use-android-relr-tags",
+ "-Wl,--no-undefined",
+ "-Wl,--hash-style=gnu",
}
)
@@ -62,4 +84,7 @@
pctx.ImportAs("ccConfig", "android/soong/cc/config")
pctx.StaticVariable("RustLinker", "${ccConfig.ClangBin}/clang++")
pctx.StaticVariable("RustLinkerArgs", "-B ${ccConfig.ClangBin} -fuse-ld=lld")
+
+ pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
+
}
diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go
index a36d61b..328bca3 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -32,6 +32,8 @@
Is64Bit() bool
Supported() bool
+
+ Bionic() bool
}
type toolchainBase struct {
@@ -53,6 +55,10 @@
panic("toolchainBase cannot determine datapath width.")
}
+func (toolchainBase) Bionic() bool {
+ return true
+}
+
type toolchain64Bit struct {
toolchainBase
}
diff --git a/rust/config/whitelist.go b/rust/config/whitelist.go
new file mode 100644
index 0000000..4646264
--- /dev/null
+++ b/rust/config/whitelist.go
@@ -0,0 +1,21 @@
+package config
+
+var (
+ RustAllowedPaths = []string{
+ "external/rust/crates",
+ "external/crosvm",
+ "external/adhd",
+ }
+
+ RustModuleTypes = []string{
+ "rust_binary",
+ "rust_binary_host",
+ "rust_library",
+ "rust_library_dylib",
+ "rust_library_rlib",
+ "rust_library_host",
+ "rust_library_host_dylib",
+ "rust_library_host_rlib",
+ "rust_proc_macro",
+ }
+)
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index cb6bf1a..5376e5b 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -61,6 +61,10 @@
return true
}
+func (toolchainLinuxX8664) Bionic() bool {
+ return false
+}
+
func (t *toolchainLinuxX8664) Name() string {
return "x86_64"
}
@@ -85,6 +89,10 @@
return true
}
+func (toolchainLinuxX86) Bionic() bool {
+ return false
+}
+
func (t *toolchainLinuxX86) Name() string {
return "x86"
}
diff --git a/rust/library.go b/rust/library.go
index 5cf8ac7..c831727 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -191,6 +191,16 @@
&library.MutatedProperties)
}
+func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+ deps = library.baseCompiler.compilerDeps(ctx, deps)
+
+ if ctx.toolchain().Bionic() && library.dylib() {
+ deps = library.baseCompiler.bionicDeps(ctx, deps)
+ }
+
+ return deps
+}
+
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
var outputFile android.WritablePath
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index d4e631b..fa69fbb 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -63,3 +63,8 @@
return srcPath
}
+
+func (prebuilt *prebuiltLibraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+ deps = prebuilt.baseCompiler.compilerDeps(ctx, deps)
+ return deps
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 4acb06f..1a247d9 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -45,7 +45,7 @@
var _ compiler = (*procMacroDecorator)(nil)
func ProcMacroFactory() android.Module {
- module, _ := NewProcMacro(android.HostAndDeviceSupported)
+ module, _ := NewProcMacro(android.HostSupportedNoCross)
return module.Init()
}
diff --git a/rust/rust.go b/rust/rust.go
index 62ccfc7..61b51e5 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -29,28 +29,11 @@
func init() {
// Only allow rust modules to be defined for certain projects
- rustModuleTypes := []string{
- "rust_binary",
- "rust_binary_host",
- "rust_library",
- "rust_library_dylib",
- "rust_library_rlib",
- "rust_library_host",
- "rust_library_host_dylib",
- "rust_library_host_rlib",
- "rust_proc_macro",
- }
-
- rustAllowedPaths := []string{
- "external/rust/crates",
- "external/crosvm",
- "external/adhd",
- }
android.AddNeverAllowRules(
android.NeverAllow().
- NotIn(rustAllowedPaths...).
- ModuleType(rustModuleTypes...))
+ NotIn(config.RustAllowedPaths...).
+ ModuleType(config.RustModuleTypes...))
android.RegisterModuleType("rust_defaults", defaultsFactory)
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -60,11 +43,12 @@
}
type Flags struct {
- GlobalFlags []string // Flags that apply globally
- RustFlags []string // Flags that apply to rust
- LinkFlags []string // Flags that apply to linker
- RustFlagsDeps android.Paths // Files depended on by compiler flags
- Toolchain config.Toolchain
+ GlobalRustFlags []string // Flags that apply globally to rust
+ GlobalLinkFlags []string // Flags that apply globally to linker
+ RustFlags []string // Flags that apply to rust
+ LinkFlags []string // Flags that apply to linker
+ RustFlagsDeps android.Paths // Files depended on by compiler flags
+ Toolchain config.Toolchain
}
type BaseProperties struct {
@@ -109,6 +93,9 @@
linkDirs []string
depFlags []string
//ReexportedDeps android.Paths
+
+ CrtBegin android.OptionalPath
+ CrtEnd android.OptionalPath
}
type RustLibraries []RustLibrary
@@ -334,17 +321,10 @@
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
- if dep.Target().Os != ctx.Os() {
- ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
- return
- }
- if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
- ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
- return
- }
if rustDep, ok := dep.(*Module); ok {
//Handle Rust Modules
+
linkFile := rustDep.outputFile
if !linkFile.Valid() {
ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
@@ -376,9 +356,6 @@
if lib, ok := rustDep.compiler.(*libraryDecorator); ok {
depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedDirs()...)
depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
- } else if procMacro, ok := rustDep.compiler.(*libraryDecorator); ok {
- depPaths.linkDirs = append(depPaths.linkDirs, procMacro.exportedDirs()...)
- depPaths.depFlags = append(depPaths.depFlags, procMacro.exportedDepFlags()...)
}
// Append this dependencies output to this mod's linkDirs so they can be exported to dependencies
@@ -393,8 +370,17 @@
}
} else if ccDep, ok := dep.(*cc.Module); ok {
-
//Handle C dependencies
+
+ if ccDep.Target().Os != ctx.Os() {
+ ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
+ return
+ }
+ if ccDep.Target().Arch.ArchType != ctx.Arch().ArchType {
+ ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
+ return
+ }
+
linkFile := ccDep.OutputFile()
linkPath := linkPathFromFilePath(linkFile.Path())
libName := libNameFromFilePath(linkFile.Path())
@@ -416,6 +402,10 @@
directSharedLibDeps = append(directSharedLibDeps, ccDep)
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
exportDep = true
+ case cc.CrtBeginDepTag():
+ depPaths.CrtBegin = linkFile
+ case cc.CrtEndDepTag():
+ depPaths.CrtEnd = linkFile
}
// Make sure these dependencies are propagated
@@ -497,7 +487,16 @@
}
actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...)
actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag(), deps.StaticLibs...)
- actx.AddDependency(mod, procMacroDepTag, deps.ProcMacros...)
+
+ if deps.CrtBegin != "" {
+ actx.AddVariationDependencies(ccDepVariations, cc.CrtBeginDepTag(), deps.CrtBegin)
+ }
+ if deps.CrtEnd != "" {
+ actx.AddVariationDependencies(ccDepVariations, cc.CrtEndDepTag(), deps.CrtEnd)
+ }
+
+ // proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
+ actx.AddFarVariationDependencies([]blueprint.Variation{{Mutator: "arch", Variation: ctx.Config().BuildOsVariant}}, procMacroDepTag, deps.ProcMacros...)
}
func (mod *Module) Name() string {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index f7c96dd..0c8d355 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -18,6 +18,7 @@
"io/ioutil"
"os"
"runtime"
+ "strings"
"testing"
"android/soong/android"
@@ -150,7 +151,6 @@
rust_proc_macro {
name: "libpm",
srcs: ["foo.rs"],
- host_supported: true,
}
rust_binary_host {
name: "fizz-buzz",
@@ -176,3 +176,28 @@
}
}
+
+// Test to make sure proc_macros use host variants when building device modules.
+func TestProcMacroDeviceDeps(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library_host_rlib {
+ name: "libbar",
+ srcs: ["foo.rs"],
+ }
+ rust_proc_macro {
+ name: "libpm",
+ rlibs: ["libbar"],
+ srcs: ["foo.rs"],
+ }
+ rust_binary {
+ name: "fizz-buzz",
+ proc_macros: ["libpm"],
+ srcs: ["foo.rs"],
+ }
+ `)
+ rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc")
+
+ if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") {
+ t.Errorf("Proc_macro is not using host variant of dependent modules.")
+ }
+}
diff --git a/rust/testing.go b/rust/testing.go
index a38697f..92347f1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/cc"
)
func GatherRequiredDepsForTest() string {
@@ -70,12 +71,101 @@
srcs: [""],
host_supported: true,
}
+
+ //////////////////////////////
+ // Device module requirements
+
+ toolchain_library {
+ name: "libgcc",
+ no_libcrt: true,
+ nocrt: true,
+ src: "",
+ system_shared_libs: [],
+ }
+ cc_library {
+ name: "libc",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ }
+ cc_library {
+ name: "libm",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ }
+ cc_library {
+ name: "libdl",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ }
+ cc_object {
+ name: "crtbegin_dynamic",
+ }
+
+ cc_object {
+ name: "crtend_android",
+ }
+ cc_library {
+ name: "liblog",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ }
+
+ //////////////////////////////
+ // cc module requirements
+
+ toolchain_library {
+ name: "libatomic",
+ src: "",
+ }
+ toolchain_library {
+ name: "libclang_rt.builtins-aarch64-android",
+ src: "",
+ }
+ toolchain_library {
+ name: "libgcc_stripped",
+ src: "",
+ }
+ cc_library {
+ name: "libc++_static",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ }
+ cc_library {
+ name: "libc++demangle",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ host_supported: false,
+ }
+ cc_library {
+ name: "libc++",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ }
+ cc_library {
+ name: "libunwind_llvm",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ }
`
return bp
}
func CreateTestContext(bp string) *android.TestContext {
ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+ ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
ctx.RegisterModuleType("rust_binary", android.ModuleFactoryAdaptor(RustBinaryFactory))
ctx.RegisterModuleType("rust_binary_host", android.ModuleFactoryAdaptor(RustBinaryHostFactory))
ctx.RegisterModuleType("rust_library", android.ModuleFactoryAdaptor(RustLibraryFactory))
@@ -86,9 +176,16 @@
ctx.RegisterModuleType("rust_library_dylib", android.ModuleFactoryAdaptor(RustLibraryDylibFactory))
ctx.RegisterModuleType("rust_proc_macro", android.ModuleFactoryAdaptor(ProcMacroFactory))
ctx.RegisterModuleType("rust_prebuilt_dylib", android.ModuleFactoryAdaptor(PrebuiltDylibFactory))
+ ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
+
+ ctx.BottomUp("image", cc.ImageMutator).Parallel()
+ ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+ ctx.BottomUp("version", cc.VersionMutator).Parallel()
+ ctx.BottomUp("begin", cc.BeginMutator).Parallel()
})
+
bp = bp + GatherRequiredDepsForTest()
mockFS := map[string][]byte{
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 52f9366..f987d98 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -29,7 +29,6 @@
# --keep-mini-debug-info
# --keep-symbols
# --keep-symbols-and-debug-frame
-# --use-gnu-strip
# --remove-build-id
set -o pipefail
@@ -44,86 +43,55 @@
--keep-mini-debug-info Keep compressed debug info in out-file
--keep-symbols Keep symbols in out-file
--keep-symbols-and-debug-frame Keep symbols and .debug_frame in out-file
- --use-gnu-strip Use strip/objcopy instead of llvm-{strip,objcopy}
--remove-build-id Remove the gnu build-id section in out-file
EOF
exit 1
}
-# Without --use-gnu-strip, GNU strip is replaced with llvm-strip to work around
-# old GNU strip bug on lld output files, b/80093681.
-# Similary, calls to objcopy are replaced with llvm-objcopy,
-# with some exceptions.
-
do_strip() {
- # ${CROSS_COMPILE}strip --strip-all does not strip .ARM.attributes,
+ # GNU strip --strip-all does not strip .ARM.attributes,
# so we tell llvm-strip to keep it too.
- if [ -z "${use_gnu_strip}" ]; then
- "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes "${infile}" -o "${outfile}.tmp"
- else
- "${CROSS_COMPILE}strip" --strip-all "${infile}" -o "${outfile}.tmp"
- fi
+ "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes "${infile}" -o "${outfile}.tmp"
}
do_strip_keep_symbols_and_debug_frame() {
- REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {if ($2 != ".debug_frame") {print "--remove-section " $2}}' | xargs`
- if [ -z "${use_gnu_strip}" ]; then
- "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
- else
- "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
- fi
+ REMOVE_SECTIONS=`"${CLANG_BIN}/llvm-readelf" -S "${infile}" | awk '/.debug_/ {if ($2 != ".debug_frame") {print "--remove-section " $2}}' | xargs`
+ "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
}
do_strip_keep_symbols() {
- REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {print "--remove-section " $2}' | xargs`
- if [ -z "${use_gnu_strip}" ]; then
- "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
- else
- "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
- fi
+ REMOVE_SECTIONS=`"${CLANG_BIN}/llvm-readelf" -S "${infile}" | awk '/.debug_/ {print "--remove-section " $2}' | xargs`
+ "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
}
do_strip_keep_symbol_list() {
echo "${symbols_to_keep}" | tr ',' '\n' > "${outfile}.symbolList"
- if [ -z "${use_gnu_strip}" ]; then
- KEEP_SYMBOLS="--strip-unneeded-symbol=.* --keep-symbols="
- KEEP_SYMBOLS+="${outfile}.symbolList"
- "${CLANG_BIN}/llvm-objcopy" --regex "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
- else
- KEEP_SYMBOLS="--strip-unneeded-symbol=* --keep-symbols="
- KEEP_SYMBOLS+="${outfile}.symbolList"
- "${CROSS_COMPILE}objcopy" -w "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
- fi
+ KEEP_SYMBOLS="--strip-unneeded-symbol=.* --keep-symbols="
+ KEEP_SYMBOLS+="${outfile}.symbolList"
+ "${CLANG_BIN}/llvm-objcopy" --regex "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
}
do_strip_keep_mini_debug_info() {
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
local fail=
- if [ -z "${use_gnu_strip}" ]; then
- "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
- else
- "${CROSS_COMPILE}strip" --strip-all -R .comment "${infile}" -o "${outfile}.tmp" || fail=true
- fi
+ "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
+
if [ -z $fail ]; then
- # Current prebult llvm-objcopy does not support the following flags:
- # --only-keep-debug --rename-section --keep-symbols
- # For the following use cases, ${CROSS_COMPILE}objcopy does fine with lld linked files,
- # except the --add-section flag.
+ # Current prebult llvm-objcopy does not support --only-keep-debug flag,
+ # and cannot process object files that are produced with the flag. Use
+ # GNU objcopy instead for now. (b/141010852)
"${CROSS_COMPILE}objcopy" --only-keep-debug "${infile}" "${outfile}.debug"
- "${CROSS_COMPILE}nm" -D "${infile}" --format=posix --defined-only 2> /dev/null | awk '{ print $1 }' | sort >"${outfile}.dynsyms"
- "${CROSS_COMPILE}nm" "${infile}" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t" || $2 == "D") print $1 }' | sort > "${outfile}.funcsyms"
+ "${CLANG_BIN}/llvm-nm" -D "${infile}" --format=posix --defined-only 2> /dev/null | awk '{ print $1 }' | sort >"${outfile}.dynsyms"
+ "${CLANG_BIN}/llvm-nm" "${infile}" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t" || $2 == "D") print $1 }' | sort > "${outfile}.funcsyms"
comm -13 "${outfile}.dynsyms" "${outfile}.funcsyms" > "${outfile}.keep_symbols"
echo >> "${outfile}.keep_symbols" # Ensure that the keep_symbols file is not empty.
"${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo"
"${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
"${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo"
"${XZ}" "${outfile}.mini_debuginfo"
- if [ -z "${use_gnu_strip}" ]; then
- "${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
- else
- "${CROSS_COMPILE}objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
- fi
+
+ "${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
else
cp -f "${infile}" "${outfile}.tmp"
@@ -131,19 +99,11 @@
}
do_add_gnu_debuglink() {
- if [ -z "${use_gnu_strip}" ]; then
- "${CLANG_BIN}/llvm-objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
- else
- "${CROSS_COMPILE}objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
- fi
+ "${CLANG_BIN}/llvm-objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
}
do_remove_build_id() {
- if [ -z "${use_gnu_strip}" ]; then
- "${CLANG_BIN}/llvm-strip" --remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id"
- else
- "${CROSS_COMPILE}strip" --remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id"
- fi
+ "${CLANG_BIN}/llvm-strip" --remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id"
rm -f "${outfile}.tmp"
mv "${outfile}.tmp.no-build-id" "${outfile}.tmp"
}
@@ -161,7 +121,6 @@
keep-symbols) keep_symbols=true ;;
keep-symbols-and-debug-frame) keep_symbols_and_debug_frame=true ;;
remove-build-id) remove_build_id=true ;;
- use-gnu-strip) use_gnu_strip=true ;;
*) echo "Unknown option --${OPTARG}"; usage ;;
esac;;
?) usage ;;
@@ -234,18 +193,13 @@
rm -f "${outfile}"
mv "${outfile}.tmp" "${outfile}"
-if [ -z "${use_gnu_strip}" ]; then
- USED_STRIP_OBJCOPY="${CLANG_BIN}/llvm-strip ${CLANG_BIN}/llvm-objcopy"
-else
- USED_STRIP_OBJCOPY="${CROSS_COMPILE}strip"
-fi
-
cat <<EOF > "${depsfile}"
${outfile}: \
${infile} \
- ${CROSS_COMPILE}nm \
${CROSS_COMPILE}objcopy \
- ${CROSS_COMPILE}readelf \
- ${USED_STRIP_OBJCOPY}
+ ${CLANG_BIN}/llvm-nm \
+ ${CLANG_BIN}/llvm-objcopy \
+ ${CLANG_BIN}/llvm-readelf \
+ ${CLANG_BIN}/llvm-strip
EOF
diff --git a/sdk/sdk.go b/sdk/sdk.go
new file mode 100644
index 0000000..fcb3fb7
--- /dev/null
+++ b/sdk/sdk.go
@@ -0,0 +1,172 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// 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 sdk
+
+import (
+ "github.com/google/blueprint"
+
+ "android/soong/android"
+ // This package doesn't depend on the apex package, but import it to make its mutators to be
+ // registered before mutators in this package. See RegisterPostDepsMutators for more details.
+ _ "android/soong/apex"
+)
+
+func init() {
+ android.RegisterModuleType("sdk", ModuleFactory)
+ android.PreDepsMutators(RegisterPreDepsMutators)
+ android.PostDepsMutators(RegisterPostDepsMutators)
+}
+
+type sdk struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ properties sdkProperties
+}
+
+type sdkProperties struct {
+ // The list of java_import modules that provide Java stubs for this SDK
+ Java_libs []string
+ Native_shared_libs []string
+}
+
+// sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
+// which Mainline modules like APEX can choose to build with.
+func ModuleFactory() android.Module {
+ s := &sdk{}
+ s.AddProperties(&s.properties)
+ android.InitAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(s)
+ return s
+}
+
+func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // TODO(jiyong): add build rules for creating stubs from members of this SDK
+}
+
+// RegisterPreDepsMutators registers pre-deps mutators to support modules implementing SdkAware
+// interface and the sdk module type. This function has been made public to be called by tests
+// outside of the sdk package
+func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("SdkMember", memberMutator).Parallel()
+ ctx.TopDown("SdkMember_deps", memberDepsMutator).Parallel()
+ ctx.BottomUp("SdkMemberInterVersion", memberInterVersionMutator).Parallel()
+}
+
+// RegisterPostDepshMutators registers post-deps mutators to support modules implementing SdkAware
+// interface and the sdk module type. This function has been made public to be called by tests
+// outside of the sdk package
+func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
+ // These must run AFTER apexMutator. Note that the apex package is imported even though there is
+ // no direct dependency to the package here. sdkDepsMutator sets the SDK requirements from an
+ // APEX to its dependents. Since different versions of the same SDK can be used by different
+ // APEXes, the apex and its dependents (which includes the dependencies to the sdk members)
+ // should have been mutated for the apex before the SDK requirements are set.
+ ctx.TopDown("SdkDepsMutator", sdkDepsMutator).Parallel()
+ ctx.BottomUp("SdkDepsReplaceMutator", sdkDepsReplaceMutator).Parallel()
+}
+
+type dependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+// For dependencies from an SDK module to its members
+// e.g. mysdk -> libfoo and libbar
+var sdkMemberDepTag dependencyTag
+
+// For dependencies from an in-development version of an SDK member to frozen versions of the same member
+// e.g. libfoo -> libfoo.mysdk.11 and libfoo.mysdk.12
+type sdkMemberVesionedDepTag struct {
+ dependencyTag
+ member string
+ version string
+}
+
+// Step 1: create dependencies from an SDK module to its members.
+func memberMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(*sdk); ok {
+ mctx.AddVariationDependencies(nil, sdkMemberDepTag, m.properties.Java_libs...)
+
+ targets := mctx.MultiTargets()
+ for _, target := range targets {
+ mctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: target.String()},
+ {Mutator: "image", Variation: "core"},
+ {Mutator: "link", Variation: "shared"},
+ }, sdkMemberDepTag, m.properties.Native_shared_libs...)
+ }
+ }
+}
+
+// Step 2: record that dependencies of SDK modules are members of the SDK modules
+func memberDepsMutator(mctx android.TopDownMutatorContext) {
+ if _, ok := mctx.Module().(*sdk); ok {
+ mySdkRef := android.ParseSdkRef(mctx, mctx.ModuleName(), "name")
+ mctx.VisitDirectDeps(func(child android.Module) {
+ if member, ok := child.(android.SdkAware); ok {
+ member.MakeMemberOf(mySdkRef)
+ }
+ })
+ }
+}
+
+// Step 3: create dependencies from the in-development version of an SDK member to frozen versions
+// of the same member. By having these dependencies, they are mutated for multiple Mainline modules
+// (apex and apk), each of which might want different sdks to be built with. For example, if both
+// apex A and B are referencing libfoo which is a member of sdk 'mysdk', the two APEXes can be
+// built with libfoo.mysdk.11 and libfoo.mysdk.12, respectively depending on which sdk they are
+// using.
+func memberInterVersionMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
+ if !m.ContainingSdk().IsCurrentVersion() {
+ memberName := m.MemberName()
+ tag := sdkMemberVesionedDepTag{member: memberName, version: m.ContainingSdk().Version}
+ mctx.AddReverseDependency(mctx.Module(), tag, memberName)
+ }
+ }
+}
+
+// Step 4: transitively ripple down the SDK requirements from the root modules like APEX to its
+// descendants
+func sdkDepsMutator(mctx android.TopDownMutatorContext) {
+ if m, ok := mctx.Module().(android.SdkAware); ok {
+ // Module types for Mainline modules (e.g. APEX) are expected to implement RequiredSdks()
+ // by reading its own properties like `uses_sdks`.
+ requiredSdks := m.RequiredSdks()
+ if len(requiredSdks) > 0 {
+ mctx.VisitDirectDeps(func(m android.Module) {
+ if dep, ok := m.(android.SdkAware); ok {
+ dep.BuildWithSdks(requiredSdks)
+ }
+ })
+ }
+ }
+}
+
+// Step 5: if libfoo.mysdk.11 is in the context where version 11 of mysdk is requested, the
+// versioned module is used instead of the un-versioned (in-development) module libfoo
+func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
+ if sdk := m.ContainingSdk(); !sdk.IsCurrentVersion() {
+ if m.RequiredSdks().Contains(sdk) {
+ // Note that this replacement is done only for the modules that have the same
+ // variations as the current module. Since current module is already mutated for
+ // apex references in other APEXes are not affected by this replacement.
+ memberName := m.MemberName()
+ mctx.ReplaceDependencies(memberName)
+ }
+ }
+ }
+}
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
new file mode 100644
index 0000000..9eca72f
--- /dev/null
+++ b/sdk/sdk_test.go
@@ -0,0 +1,318 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sdk
+
+import (
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/apex"
+ "android/soong/cc"
+ "android/soong/java"
+)
+
+func testSdkContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
+ config := android.TestArchConfig(buildDir, nil)
+ ctx := android.NewTestArchContext()
+
+ // from android package
+ ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
+ })
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
+ ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
+ })
+
+ // from java package
+ ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
+ ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
+ ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
+
+ // from cc package
+ ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+ ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
+ ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+ ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(cc.PrebuiltSharedLibraryFactory))
+ ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(cc.PrebuiltStaticLibraryFactory))
+ ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
+ ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("image", cc.ImageMutator).Parallel()
+ ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+ ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
+ ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
+ ctx.BottomUp("version", cc.VersionMutator).Parallel()
+ ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+ })
+
+ // from apex package
+ ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apex.BundleFactory))
+ ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apex.ApexKeyFactory))
+ ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
+
+ // from this package
+ ctx.RegisterModuleType("sdk", android.ModuleFactoryAdaptor(ModuleFactory))
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
+
+ ctx.Register()
+
+ bp = bp + `
+ apex_key {
+ name: "myapex.key",
+ public_key: "myapex.avbpubkey",
+ private_key: "myapex.pem",
+ }
+
+ android_app_certificate {
+ name: "myapex.cert",
+ certificate: "myapex",
+ }
+ ` + cc.GatherRequiredDepsForTest(android.Android)
+
+ ctx.MockFileSystem(map[string][]byte{
+ "Android.bp": []byte(bp),
+ "build/make/target/product/security": nil,
+ "apex_manifest.json": nil,
+ "system/sepolicy/apex/myapex-file_contexts": nil,
+ "system/sepolicy/apex/myapex2-file_contexts": nil,
+ "myapex.avbpubkey": nil,
+ "myapex.pem": nil,
+ "myapex.x509.pem": nil,
+ "myapex.pk8": nil,
+ "Test.java": nil,
+ "Test.cpp": nil,
+ "libfoo.so": nil,
+ })
+
+ return ctx, config
+}
+
+func testSdk(t *testing.T, bp string) (*android.TestContext, android.Config) {
+ ctx, config := testSdkContext(t, bp)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+ return ctx, config
+}
+
+// ensure that 'result' contains 'expected'
+func ensureContains(t *testing.T, result string, expected string) {
+ t.Helper()
+ if !strings.Contains(result, expected) {
+ t.Errorf("%q is not found in %q", expected, result)
+ }
+}
+
+// ensures that 'result' does not contain 'notExpected'
+func ensureNotContains(t *testing.T, result string, notExpected string) {
+ t.Helper()
+ if strings.Contains(result, notExpected) {
+ t.Errorf("%q is found in %q", notExpected, result)
+ }
+}
+
+func ensureListContains(t *testing.T, result []string, expected string) {
+ t.Helper()
+ if !android.InList(expected, result) {
+ t.Errorf("%q is not found in %v", expected, result)
+ }
+}
+
+func ensureListNotContains(t *testing.T, result []string, notExpected string) {
+ t.Helper()
+ if android.InList(notExpected, result) {
+ t.Errorf("%q is found in %v", notExpected, result)
+ }
+}
+
+func pathsToStrings(paths android.Paths) []string {
+ ret := []string{}
+ for _, p := range paths {
+ ret = append(ret, p.String())
+ }
+ return ret
+}
+
+func TestBasicSdkWithJava(t *testing.T) {
+ ctx, _ := testSdk(t, `
+ sdk {
+ name: "mysdk#1",
+ java_libs: ["sdkmember_mysdk_1"],
+ }
+
+ sdk {
+ name: "mysdk#2",
+ java_libs: ["sdkmember_mysdk_2"],
+ }
+
+ java_import {
+ name: "sdkmember",
+ prefer: false,
+ host_supported: true,
+ }
+
+ java_import {
+ name: "sdkmember_mysdk_1",
+ sdk_member_name: "sdkmember",
+ host_supported: true,
+ }
+
+ java_import {
+ name: "sdkmember_mysdk_2",
+ sdk_member_name: "sdkmember",
+ host_supported: true,
+ }
+
+ java_library {
+ name: "myjavalib",
+ srcs: ["Test.java"],
+ libs: ["sdkmember"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ host_supported: true,
+ }
+
+ apex {
+ name: "myapex",
+ java_libs: ["myjavalib"],
+ uses_sdks: ["mysdk#1"],
+ key: "myapex.key",
+ certificate: ":myapex.cert",
+ }
+
+ apex {
+ name: "myapex2",
+ java_libs: ["myjavalib"],
+ uses_sdks: ["mysdk#2"],
+ key: "myapex.key",
+ certificate: ":myapex.cert",
+ }
+ `)
+
+ sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_common_myapex").Rule("combineJar").Output
+ sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_common_myapex2").Rule("combineJar").Output
+
+ javalibForMyApex := ctx.ModuleForTests("myjavalib", "android_common_myapex")
+ javalibForMyApex2 := ctx.ModuleForTests("myjavalib", "android_common_myapex2")
+
+ // Depending on the uses_sdks value, different libs are linked
+ ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
+ ensureListContains(t, pathsToStrings(javalibForMyApex2.Rule("javac").Implicits), sdkMemberV2.String())
+}
+
+func TestBasicSdkWithCc(t *testing.T) {
+ ctx, _ := testSdk(t, `
+ sdk {
+ name: "mysdk#1",
+ native_shared_libs: ["sdkmember_mysdk_1"],
+ }
+
+ sdk {
+ name: "mysdk#2",
+ native_shared_libs: ["sdkmember_mysdk_2"],
+ }
+
+ cc_prebuilt_library_shared {
+ name: "sdkmember",
+ srcs: ["libfoo.so"],
+ prefer: false,
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_prebuilt_library_shared {
+ name: "sdkmember_mysdk_1",
+ sdk_member_name: "sdkmember",
+ srcs: ["libfoo.so"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_prebuilt_library_shared {
+ name: "sdkmember_mysdk_2",
+ sdk_member_name: "sdkmember",
+ srcs: ["libfoo.so"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library_shared {
+ name: "mycpplib",
+ srcs: ["Test.cpp"],
+ shared_libs: ["sdkmember"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ apex {
+ name: "myapex",
+ native_shared_libs: ["mycpplib"],
+ uses_sdks: ["mysdk#1"],
+ key: "myapex.key",
+ certificate: ":myapex.cert",
+ }
+
+ apex {
+ name: "myapex2",
+ native_shared_libs: ["mycpplib"],
+ uses_sdks: ["mysdk#2"],
+ key: "myapex.key",
+ certificate: ":myapex.cert",
+ }
+ `)
+
+ sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_core_shared_myapex").Rule("toc").Output
+ sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_core_shared_myapex2").Rule("toc").Output
+
+ cpplibForMyApex := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex")
+ cpplibForMyApex2 := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex2")
+
+ // Depending on the uses_sdks value, different libs are linked
+ ensureListContains(t, pathsToStrings(cpplibForMyApex.Rule("ld").Implicits), sdkMemberV1.String())
+ ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
+}
+
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_sdk_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index c7669bd..a876341 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -32,6 +32,86 @@
name string
}
+type syspropGenProperties struct {
+ Srcs []string `android:"path"`
+ Scope string
+}
+
+type syspropJavaGenRule struct {
+ android.ModuleBase
+
+ properties syspropGenProperties
+
+ genSrcjars android.Paths
+}
+
+var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil)
+
+var (
+ syspropJava = pctx.AndroidStaticRule("syspropJava",
+ blueprint.RuleParams{
+ Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
+ `$syspropJavaCmd --scope $scope --java-output-dir $out.tmp $in && ` +
+ `$soongZipCmd -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
+ CommandDeps: []string{
+ "$syspropJavaCmd",
+ "$soongZipCmd",
+ },
+ }, "scope")
+)
+
+func init() {
+ pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
+ pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
+
+ android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
+ })
+}
+
+func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var checkApiFileTimeStamp android.WritablePath
+
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ if m, ok := dep.(*syspropLibrary); ok {
+ checkApiFileTimeStamp = m.checkApiFileTimeStamp
+ }
+ })
+
+ for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
+ srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: syspropJava,
+ Description: "sysprop_java " + syspropFile.Rel(),
+ Output: srcJarFile,
+ Input: syspropFile,
+ Implicit: checkApiFileTimeStamp,
+ Args: map[string]string{
+ "scope": g.properties.Scope,
+ },
+ })
+
+ g.genSrcjars = append(g.genSrcjars, srcJarFile)
+ }
+}
+
+func (g *syspropJavaGenRule) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return g.genSrcjars, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
+func syspropJavaGenFactory() android.Module {
+ g := &syspropJavaGenRule{}
+ g.AddProperties(&g.properties)
+ android.InitAndroidModule(g)
+ return g
+}
+
type syspropLibrary struct {
android.ModuleBase
@@ -81,13 +161,29 @@
return "lib" + m.BaseModuleName()
}
+func (m *syspropLibrary) javaGenModuleName() string {
+ return m.BaseModuleName() + "_java_gen"
+}
+
func (m *syspropLibrary) BaseModuleName() string {
return m.ModuleBase.Name()
}
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- m.currentApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-current.txt")
- m.latestApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-latest.txt")
+ baseModuleName := m.BaseModuleName()
+
+ for _, syspropFile := range android.PathsForModuleSrc(ctx, m.properties.Srcs) {
+ if syspropFile.Ext() != ".sysprop" {
+ ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
+ }
+ }
+
+ if ctx.Failed() {
+ return
+ }
+
+ m.currentApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", baseModuleName+"-current.txt")
+ m.latestApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", baseModuleName+"-latest.txt")
// dump API rule
rule := android.NewRuleBuilder()
@@ -96,7 +192,7 @@
BuiltTool(ctx, "sysprop_api_dump").
Output(m.dumpedApiFile).
Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs))
- rule.Build(pctx, ctx, m.BaseModuleName()+"_api_dump", m.BaseModuleName()+" api dump")
+ rule.Build(pctx, ctx, baseModuleName+"_api_dump", baseModuleName+" api dump")
// check API rule
rule = android.NewRuleBuilder()
@@ -105,8 +201,8 @@
msg := fmt.Sprintf(`\n******************************\n`+
`API of sysprop_library %s doesn't match with current.txt\n`+
`Please update current.txt by:\n`+
- `rm -rf %q && cp -f %q %q\n`+
- `******************************\n`, m.BaseModuleName(),
+ `m %s-dump-api && rm -rf %q && cp -f %q %q\n`+
+ `******************************\n`, baseModuleName, baseModuleName,
m.currentApiFile.String(), m.dumpedApiFile.String(), m.currentApiFile.String())
rule.Command().
@@ -121,7 +217,7 @@
msg = fmt.Sprintf(`\n******************************\n`+
`API of sysprop_library %s doesn't match with latest version\n`+
`Please fix the breakage and rebuild.\n`+
- `******************************\n`, m.BaseModuleName())
+ `******************************\n`, baseModuleName)
rule.Command().
Text("( ").
@@ -138,7 +234,7 @@
Text("touch").
Output(m.checkApiFileTimeStamp)
- rule.Build(pctx, ctx, m.BaseModuleName()+"_check_api", m.BaseModuleName()+" check api")
+ rule.Build(pctx, ctx, baseModuleName+"_check_api", baseModuleName+" check api")
}
func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
@@ -153,13 +249,13 @@
fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
fmt.Fprintf(w, "\ttouch $@\n\n")
- fmt.Fprintf(w, ".PHONY: %s-check-api\n\n", name)
+ fmt.Fprintf(w, ".PHONY: %s-check-api %s-dump-api\n\n", name, name)
+
+ // dump API rule
+ fmt.Fprintf(w, "%s-dump-api: %s\n\n", name, m.dumpedApiFile.String())
// check API rule
fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String())
-
- // "make {sysprop_library}" should also build the C++ library
- fmt.Fprintf(w, "%s: %s\n\n", name, m.CcModuleName())
}}
}
@@ -263,14 +359,38 @@
ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
ccProps.Header_libs = []string{"libbase_headers"}
ccProps.Shared_libs = []string{"liblog"}
-
- // add sysprop_library module to perform check API
- ccProps.Required = []string{m.Name()}
- ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
ccProps.Recovery_available = m.properties.Recovery_available
ccProps.Vendor_available = m.properties.Vendor_available
- ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &ccProps)
+ ctx.CreateModule(cc.LibraryFactory, &ccProps)
+
+ // internal scope contains all properties
+ // public scope only contains public properties
+ // use public if the owner is different from client
+ scope := "internal"
+ isProduct := ctx.ProductSpecific()
+ isVendor := ctx.SocSpecific()
+ isOwnerPlatform := owner == "Platform"
+
+ if isProduct {
+ // product can't own any sysprop_library now, so product must use public scope
+ scope = "public"
+ } else if isVendor && !isOwnerPlatform {
+ // vendor and odm can't use system's internal property.
+ scope = "public"
+ }
+
+ javaGenProps := struct {
+ Srcs []string
+ Scope string
+ Name *string
+ }{
+ Srcs: m.properties.Srcs,
+ Scope: scope,
+ Name: proptools.StringPtr(m.javaGenModuleName()),
+ }
+
+ ctx.CreateModule(syspropJavaGenFactory, &javaGenProps)
javaProps := struct {
Name *string
@@ -278,27 +398,26 @@
Soc_specific *bool
Device_specific *bool
Product_specific *bool
- Sysprop struct {
- Platform *bool
- }
- Required []string
- Sdk_version *string
- Installable *bool
- Libs []string
+ Required []string
+ Sdk_version *string
+ Installable *bool
+ Libs []string
}{}
javaProps.Name = proptools.StringPtr(m.BaseModuleName())
- javaProps.Srcs = m.properties.Srcs
+ javaProps.Srcs = []string{":" + *javaGenProps.Name}
javaProps.Soc_specific = proptools.BoolPtr(socSpecific)
javaProps.Device_specific = proptools.BoolPtr(deviceSpecific)
javaProps.Product_specific = proptools.BoolPtr(productSpecific)
javaProps.Installable = m.properties.Installable
-
- // add sysprop_library module to perform check API
- javaProps.Required = []string{m.Name()}
javaProps.Sdk_version = proptools.StringPtr("core_current")
- javaProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
javaProps.Libs = []string{stub}
- ctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory), &javaProps)
+ ctx.CreateModule(java.LibraryFactory, &javaProps)
+}
+
+func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
+ if m, ok := ctx.Module().(*syspropLibrary); ok {
+ ctx.AddReverseDependency(m, nil, m.javaGenModuleName())
+ }
}
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 5345770..6b4337a 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -62,6 +62,9 @@
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
+ })
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
@@ -282,10 +285,10 @@
// Check for generated cc_library
for _, variant := range []string{
- "android_arm_armv7-a-neon_vendor_shared",
- "android_arm_armv7-a-neon_vendor_static",
- "android_arm64_armv8-a_vendor_shared",
- "android_arm64_armv8-a_vendor_static",
+ "android_arm_armv7-a-neon_vendor.VER_shared",
+ "android_arm_armv7-a-neon_vendor.VER_static",
+ "android_arm64_armv8-a_vendor.VER_shared",
+ "android_arm64_armv8-a_vendor.VER_static",
} {
ctx.ModuleForTests("libsysprop-platform", variant)
ctx.ModuleForTests("libsysprop-vendor", variant)
@@ -309,15 +312,15 @@
// Check for exported includes
coreVariant := "android_arm64_armv8-a_core_static"
- vendorVariant := "android_arm64_armv8-a_vendor_static"
+ vendorVariant := "android_arm64_armv8-a_vendor.VER_static"
platformInternalPath := "libsysprop-platform/android_arm64_armv8-a_core_static/gen/sysprop/include"
platformPublicCorePath := "libsysprop-platform/android_arm64_armv8-a_core_static/gen/sysprop/public/include"
- platformPublicVendorPath := "libsysprop-platform/android_arm64_armv8-a_vendor_static/gen/sysprop/public/include"
+ platformPublicVendorPath := "libsysprop-platform/android_arm64_armv8-a_vendor.VER_static/gen/sysprop/public/include"
platformOnProductPath := "libsysprop-platform-on-product/android_arm64_armv8-a_core_static/gen/sysprop/public/include"
- vendorInternalPath := "libsysprop-vendor/android_arm64_armv8-a_vendor_static/gen/sysprop/include"
+ vendorInternalPath := "libsysprop-vendor/android_arm64_armv8-a_vendor.VER_static/gen/sysprop/include"
vendorPublicPath := "libsysprop-vendor/android_arm64_armv8-a_core_static/gen/sysprop/public/include"
platformClient := ctx.ModuleForTests("cc-client-platform", coreVariant)
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 7cd7c5a..3d30cfa 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -44,10 +44,11 @@
CommandDeps: []string{"$template"},
}, "name", "template", "extraConfigs")
-func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string) (path android.Path, autogenPath android.WritablePath) {
- if p := getTestConfig(ctx, prop); p != nil {
+func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool) (path android.Path, autogenPath android.WritablePath) {
+ p := getTestConfig(ctx, prop)
+ if !Bool(autoGenConfig) && p != nil {
return p, nil
- } else if !android.InList("cts", testSuites) {
+ } else if !android.InList("cts", testSuites) && BoolDefault(autoGenConfig, true) {
outputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".config")
return nil, outputFile
} else {
@@ -73,26 +74,34 @@
return fmt.Sprintf(`<option name="%s" value="%s" />`, o.Name, o.Value)
}
-type Preparer struct {
+// It can be a template of object or target_preparer.
+type Object struct {
+ // Set it as a target_preparer if object type == "target_preparer".
+ Type string
Class string
Options []Option
}
-var _ Config = Preparer{}
+var _ Config = Object{}
-func (p Preparer) Config() string {
+func (ob Object) Config() string {
var optionStrings []string
- for _, option := range p.Options {
+ for _, option := range ob.Options {
optionStrings = append(optionStrings, option.Config())
}
var options string
- if len(p.Options) == 0 {
+ if len(ob.Options) == 0 {
options = ""
} else {
optionDelimiter := fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)
options = optionDelimiter + strings.Join(optionStrings, optionDelimiter)
}
- return fmt.Sprintf(`<target_preparer class="%s">%s\n%s</target_preparer>`, p.Class, options, test_xml_indent)
+ if ob.Type == "target_preparer" {
+ return fmt.Sprintf(`<target_preparer class="%s">%s\n%s</target_preparer>`, ob.Class, options, test_xml_indent)
+ } else {
+ return fmt.Sprintf(`<object type="%s" class="%s">%s\n%s</object>`, ob.Type, ob.Class, options, test_xml_indent)
+ }
+
}
func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, configs []Config) {
@@ -116,8 +125,8 @@
}
func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
- testConfigTemplateProp *string, testSuites []string, config []Config) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+ testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -135,8 +144,8 @@
}
func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
- testConfigTemplateProp *string, testSuites []string, configs []Config) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+ testConfigTemplateProp *string, testSuites []string, configs []Config, autoGenConfig *bool) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -149,8 +158,9 @@
return path
}
-func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, testSuites []string) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
+ testSuites []string, autoGenConfig *bool) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -168,9 +178,9 @@
}
func AutoGenPythonBinaryHostTestConfig(ctx android.ModuleContext, testConfigProp *string,
- testConfigTemplateProp *string, testSuites []string) android.Path {
+ testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -192,8 +202,9 @@
},
}, "name", "template")
-func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, manifest android.Path, testSuites []string) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string,
+ testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
if autogenPath != nil {
template := "${InstrumentationTestConfigTemplate}"
moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp)
@@ -214,3 +225,6 @@
}
return path
}
+
+var Bool = proptools.Bool
+var BoolDefault = proptools.BoolDefault
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index bfe2c36..0a2b510 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -87,6 +87,7 @@
// otherwise we'd have to rebuild any generated files created with
// those tools.
removeGlobs(ctx,
+ hostOut("apex"),
hostOut("obj/NOTICE_FILES"),
hostOut("obj/PACKAGING"),
hostOut("coverage"),
diff --git a/ui/build/config.go b/ui/build/config.go
index 665d2f0..def3345 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -16,7 +16,6 @@
import (
"io/ioutil"
- "log"
"os"
"path/filepath"
"runtime"
@@ -189,27 +188,27 @@
checkTopDir(ctx)
if srcDir := absPath(ctx, "."); strings.ContainsRune(srcDir, ' ') {
- log.Println("You are building in a directory whose absolute path contains a space character:")
- log.Println()
- log.Printf("%q\n", srcDir)
- log.Println()
- log.Fatalln("Directory names containing spaces are not supported")
+ ctx.Println("You are building in a directory whose absolute path contains a space character:")
+ ctx.Println()
+ ctx.Printf("%q\n", srcDir)
+ ctx.Println()
+ ctx.Fatalln("Directory names containing spaces are not supported")
}
if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
- log.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
- log.Println()
- log.Printf("%q\n", outDir)
- log.Println()
- log.Fatalln("Directory names containing spaces are not supported")
+ ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
+ ctx.Println()
+ ctx.Printf("%q\n", outDir)
+ ctx.Println()
+ ctx.Fatalln("Directory names containing spaces are not supported")
}
if distDir := ret.DistDir(); strings.ContainsRune(distDir, ' ') {
- log.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
- log.Println()
- log.Printf("%q\n", distDir)
- log.Println()
- log.Fatalln("Directory names containing spaces are not supported")
+ ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
+ ctx.Println()
+ ctx.Printf("%q\n", distDir)
+ ctx.Println()
+ ctx.Fatalln("Directory names containing spaces are not supported")
}
// Configure Java-related variables, including adding it to $PATH
diff --git a/ui/terminal/smart_status.go b/ui/terminal/smart_status.go
index 57f71ab..efcfd43 100644
--- a/ui/terminal/smart_status.go
+++ b/ui/terminal/smart_status.go
@@ -189,7 +189,7 @@
fmt.Fprintf(s.writer, ansi.resetScrollingMargins())
_, height, _ := termSize(s.writer)
// Move the cursor to the top of the now-blank, previously non-scrolling region
- fmt.Fprintf(s.writer, ansi.setCursor(height-s.tableHeight, 0))
+ fmt.Fprintf(s.writer, ansi.setCursor(height-s.tableHeight, 1))
// Turn the cursor back on
fmt.Fprintf(s.writer, ansi.showCursor())
}
@@ -334,52 +334,44 @@
scrollingHeight := s.termHeight - s.tableHeight
// Update the scrolling region in case the height of the terminal changed
- fmt.Fprint(s.writer, ansi.setScrollingMargins(0, scrollingHeight))
- // Move the cursor to the first line of the non-scrolling region
- fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight+1, 0))
+
+ fmt.Fprint(s.writer, ansi.setScrollingMargins(1, scrollingHeight))
// Write as many status lines as fit in the table
- var tableLine int
- var runningAction actionTableEntry
- for tableLine, runningAction = range s.runningActions {
+ for tableLine := 0; tableLine < s.tableHeight; tableLine++ {
if tableLine >= s.tableHeight {
break
}
+ // Move the cursor to the correct line of the non-scrolling region
+ fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight+1+tableLine, 1))
- seconds := int(time.Since(runningAction.startTime).Round(time.Second).Seconds())
+ if tableLine < len(s.runningActions) {
+ runningAction := s.runningActions[tableLine]
- desc := runningAction.action.Description
- if desc == "" {
- desc = runningAction.action.Command
+ seconds := int(time.Since(runningAction.startTime).Round(time.Second).Seconds())
+
+ desc := runningAction.action.Description
+ if desc == "" {
+ desc = runningAction.action.Command
+ }
+
+ color := ""
+ if seconds >= 60 {
+ color = ansi.red() + ansi.bold()
+ } else if seconds >= 30 {
+ color = ansi.yellow() + ansi.bold()
+ }
+
+ durationStr := fmt.Sprintf(" %2d:%02d ", seconds/60, seconds%60)
+ desc = elide(desc, s.termWidth-len(durationStr))
+ durationStr = color + durationStr + ansi.regular()
+ fmt.Fprint(s.writer, durationStr, desc)
}
-
- color := ""
- if seconds >= 60 {
- color = ansi.red() + ansi.bold()
- } else if seconds >= 30 {
- color = ansi.yellow() + ansi.bold()
- }
-
- durationStr := fmt.Sprintf(" %2d:%02d ", seconds/60, seconds%60)
- desc = elide(desc, s.termWidth-len(durationStr))
- durationStr = color + durationStr + ansi.regular()
-
- fmt.Fprint(s.writer, durationStr, desc, ansi.clearToEndOfLine())
- if tableLine < s.tableHeight-1 {
- fmt.Fprint(s.writer, "\n")
- }
- }
-
- // Clear any remaining lines in the table
- for ; tableLine < s.tableHeight; tableLine++ {
fmt.Fprint(s.writer, ansi.clearToEndOfLine())
- if tableLine < s.tableHeight-1 {
- fmt.Fprint(s.writer, "\n")
- }
}
// Move the cursor back to the last line of the scrolling region
- fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight, 0))
+ fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight, 1))
}
var ansi = ansiImpl{}
diff --git a/ui/terminal/status.go b/ui/terminal/status.go
index 69a2a09..60dfc70 100644
--- a/ui/terminal/status.go
+++ b/ui/terminal/status.go
@@ -26,10 +26,10 @@
//
// statusFormat takes nearly all the same options as NINJA_STATUS.
// %c is currently unsupported.
-func NewStatusOutput(w io.Writer, statusFormat string, quietBuild bool) status.StatusOutput {
+func NewStatusOutput(w io.Writer, statusFormat string, forceDumbOutput, quietBuild bool) status.StatusOutput {
formatter := newFormatter(statusFormat, quietBuild)
- if isSmartTerminal(w) {
+ if !forceDumbOutput && isSmartTerminal(w) {
return NewSmartStatusOutput(w, formatter)
} else {
return NewDumbStatusOutput(w, formatter)
diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go
index 81aa238..9f60829 100644
--- a/ui/terminal/status_test.go
+++ b/ui/terminal/status_test.go
@@ -94,7 +94,7 @@
t.Run("smart", func(t *testing.T) {
smart := &fakeSmartTerminal{termWidth: 40}
- stat := NewStatusOutput(smart, "", false)
+ stat := NewStatusOutput(smart, "", false, false)
tt.calls(stat)
stat.Flush()
@@ -105,7 +105,7 @@
t.Run("dumb", func(t *testing.T) {
dumb := &bytes.Buffer{}
- stat := NewStatusOutput(dumb, "", false)
+ stat := NewStatusOutput(dumb, "", false, false)
tt.calls(stat)
stat.Flush()
@@ -113,6 +113,17 @@
t.Errorf("want:\n%q\ngot:\n%q", w, g)
}
})
+
+ t.Run("force dumb", func(t *testing.T) {
+ smart := &fakeSmartTerminal{termWidth: 40}
+ stat := NewStatusOutput(smart, "", true, false)
+ tt.calls(stat)
+ stat.Flush()
+
+ if g, w := smart.String(), tt.dumb; g != w {
+ t.Errorf("want:\n%q\ngot:\n%q", w, g)
+ }
+ })
})
}
}
@@ -258,7 +269,7 @@
os.Setenv(tableHeightEnVar, "")
smart := &fakeSmartTerminal{termWidth: 40}
- stat := NewStatusOutput(smart, "", false)
+ stat := NewStatusOutput(smart, "", false, false)
smartStat := stat.(*smartStatusOutput)
smartStat.sigwinchHandled = make(chan bool)
diff --git a/vnames.json b/vnames.json
new file mode 100644
index 0000000..7b34c52
--- /dev/null
+++ b/vnames.json
@@ -0,0 +1,18 @@
+[
+ {
+ "pattern": "out/(.*)",
+ "vname": {
+ "corpus": "CORPUS",
+ "root": "out",
+ "path": "@1@"
+ }
+ },
+ {
+ "pattern": "(.*)",
+ "vname": {
+ "corpus": "CORPUS",
+ "path": "@1@"
+ }
+ }
+]
+