Merge "Shard gensrcs modules into multiple commands"
diff --git a/Android.bp b/Android.bp
index 7e6da6e..1dfac87 100644
--- a/Android.bp
+++ b/Android.bp
@@ -172,6 +172,7 @@
"cc/vndk_prebuilt.go",
"cc/xom.go",
+ "cc/cflag_artifacts.go",
"cc/cmakelists.go",
"cc/compdb.go",
"cc/compiler.go",
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..348b064 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -527,7 +527,6 @@
CpuVariant string
Abi []string
ArchFeatures []string
- Native bool
}
func (a Arch) String() string {
@@ -855,149 +854,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 +957,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) {
@@ -1482,11 +1360,6 @@
addTarget(Android, *variables.DeviceSecondaryArch,
variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
variables.DeviceSecondaryAbi, NativeBridgeDisabled, nil, nil)
-
- deviceArches := targets[Android]
- if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
- deviceArches[1].Arch.Native = false
- }
}
if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" {
@@ -1634,7 +1507,7 @@
if err != nil {
return nil, err
}
- arch.Native = false
+
ret = append(ret, Target{
Os: Android,
Arch: arch,
@@ -1663,7 +1536,6 @@
ArchVariant: stringPtr(archVariant),
CpuVariant: stringPtr(cpuVariant),
Abi: abi,
- Native: true,
}
if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
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..26c4e6e 100644
--- a/android/config.go
+++ b/android/config.go
@@ -93,6 +93,10 @@
BuildOsVariant string
BuildOsCommonVariant string
+ // multilibConflicts for an ArchType is true if there is earlier configured device architecture with the same
+ // multilib value.
+ multilibConflicts map[ArchType]bool
+
deviceConfig *deviceConfig
srcDir string // the path of the root source directory
@@ -240,10 +244,10 @@
config := testConfig.config
config.Targets[Android] = []Target{
- {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
- {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
- {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64"},
- {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm"},
+ {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
+ {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64"},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm"},
}
return testConfig
@@ -255,7 +259,7 @@
config.Targets = map[OsType][]Target{
Fuchsia: []Target{
- {Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Native: true}, NativeBridgeDisabled, "", ""},
+ {Fuchsia, Arch{ArchType: Arm64, ArchVariant: ""}, NativeBridgeDisabled, "", ""},
},
BuildOs: []Target{
{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
@@ -272,8 +276,8 @@
config.Targets = map[OsType][]Target{
Android: []Target{
- {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
- {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
},
BuildOs: []Target{
{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
@@ -305,8 +309,9 @@
env: originalEnv,
- srcDir: srcDir,
- buildDir: buildDir,
+ srcDir: srcDir,
+ buildDir: buildDir,
+ multilibConflicts: make(map[ArchType]bool),
}
config.deviceConfig = &deviceConfig{
@@ -360,6 +365,14 @@
targets[Android] = androidTargets
}
+ multilib := make(map[string]bool)
+ for _, target := range targets[Android] {
+ if seen := multilib[target.Arch.ArchType.Multilib]; seen {
+ config.multilibConflicts[target.Arch.ArchType] = true
+ }
+ multilib[target.Arch.ArchType.Multilib] = true
+ }
+
config.Targets = targets
config.BuildOsVariant = targets[BuildOs][0].String()
config.BuildOsCommonVariant = getCommonTargets(targets[BuildOs])[0].String()
@@ -800,7 +813,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)
@@ -852,6 +865,10 @@
return Bool(c.productVariables.VndkSnapshotBuildArtifacts)
}
+func (c *config) HasMultilibConflict(arch ArchType) bool {
+ return c.multilibConflicts[arch]
+}
+
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
for _, target := range c.config.Targets[Android] {
@@ -1009,19 +1026,6 @@
return "", false
}
-// SecondArchIsTranslated returns true if the primary device arch is X86 or X86_64 and the device also has an arch
-// that is Arm or Arm64.
-func (c *config) SecondArchIsTranslated() bool {
- deviceTargets := c.Targets[Android]
- if len(deviceTargets) < 2 {
- return false
- }
-
- arch := deviceTargets[0].Arch
-
- return (arch.ArchType == X86 || arch.ArchType == X86_64) && hasArmAndroidArch(deviceTargets)
-}
-
func (c *config) IntegerOverflowDisabledForPath(path string) bool {
if c.productVariables.IntegerOverflowExcludePaths == nil {
return false
diff --git a/android/hooks.go b/android/hooks.go
index 64ffd52..604cb9c 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -30,7 +30,7 @@
BaseModuleContext
AppendProperties(...interface{})
PrependProperties(...interface{})
- CreateModule(ModuleFactory, ...interface{})
+ CreateModule(ModuleFactory, ...interface{}) Module
}
// Arch hooks are run after the module has been split into architecture variants, and can be used
@@ -75,7 +75,7 @@
type InstallHookContext interface {
ModuleContext
- Path() OutputPath
+ Path() InstallPath
Symlink() bool
}
@@ -89,11 +89,11 @@
type installHookContext struct {
ModuleContext
- path OutputPath
+ path InstallPath
symlink bool
}
-func (x *installHookContext) Path() OutputPath {
+func (x *installHookContext) Path() InstallPath {
return x.path
}
@@ -101,7 +101,7 @@
return x.symlink
}
-func (x *hooks) runInstallHooks(ctx ModuleContext, path OutputPath, symlink bool) {
+func (x *hooks) runInstallHooks(ctx ModuleContext, path InstallPath, symlink bool) {
if len(x.install) > 0 {
mctx := &installHookContext{
ModuleContext: ctx,
diff --git a/android/module.go b/android/module.go
index 8076a99..5d1a609 100644
--- a/android/module.go
+++ b/android/module.go
@@ -147,15 +147,17 @@
ExpandSource(srcFile, prop string) Path
ExpandOptionalSource(srcFile *string, prop string) OptionalPath
- InstallExecutable(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
- InstallFile(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
- InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath
- InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath
+ InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
+ InstallFile(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
+ InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
+ InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
CheckbuildFile(srcPath Path)
InstallInData() bool
+ InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
+ InstallInRoot() bool
InstallBypassMake() bool
RequiredModuleNames() []string
@@ -192,8 +194,10 @@
Enabled() bool
Target() Target
InstallInData() bool
+ InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
+ InstallInRoot() bool
InstallBypassMake() bool
SkipInstall()
ExportedToMake() bool
@@ -510,8 +514,19 @@
m.AddProperties(
&base.nameProperties,
- &base.commonProperties,
- &base.variableProperties)
+ &base.commonProperties)
+
+ // Allow tests to override the default product variables
+ if base.variableProperties == nil {
+ base.variableProperties = zeroProductVariables
+ }
+
+ // Filter the product variables properties to the ones that exist on this module
+ base.variableProperties = createVariableProperties(m.GetProperties(), base.variableProperties)
+ if base.variableProperties != nil {
+ m.AddProperties(base.variableProperties)
+ }
+
base.generalProperties = m.GetProperties()
base.customizableProperties = m.GetProperties()
@@ -593,7 +608,7 @@
nameProperties nameProperties
commonProperties commonProperties
- variableProperties variableProperties
+ variableProperties interface{}
hostAndDeviceProperties hostAndDeviceProperties
generalProperties []interface{}
archProperties [][]interface{}
@@ -832,6 +847,10 @@
return false
}
+func (m *ModuleBase) InstallInTestcases() bool {
+ return false
+}
+
func (m *ModuleBase) InstallInSanitizerDir() bool {
return false
}
@@ -840,6 +859,10 @@
return Bool(m.commonProperties.Recovery)
}
+func (m *ModuleBase) InstallInRoot() bool {
+ return false
+}
+
func (m *ModuleBase) InstallBypassMake() bool {
return false
}
@@ -1177,6 +1200,12 @@
func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
argNames ...string) blueprint.Rule {
+ if m.config.UseGoma() && params.Pool == nil {
+ // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
+ // local parallelism value
+ params.Pool = localPool
+ }
+
rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
if m.config.captureBuild {
@@ -1504,6 +1533,10 @@
return m.module.InstallInData()
}
+func (m *moduleContext) InstallInTestcases() bool {
+ return m.module.InstallInTestcases()
+}
+
func (m *moduleContext) InstallInSanitizerDir() bool {
return m.module.InstallInSanitizerDir()
}
@@ -1512,11 +1545,15 @@
return m.module.InstallInRecovery()
}
+func (m *moduleContext) InstallInRoot() bool {
+ return m.module.InstallInRoot()
+}
+
func (m *moduleContext) InstallBypassMake() bool {
return m.module.InstallBypassMake()
}
-func (m *moduleContext) skipInstall(fullInstallPath OutputPath) bool {
+func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
if m.module.base().commonProperties.SkipInstall {
return true
}
@@ -1541,18 +1578,18 @@
return false
}
-func (m *moduleContext) InstallFile(installPath OutputPath, name string, srcPath Path,
- deps ...Path) OutputPath {
+func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
+ deps ...Path) InstallPath {
return m.installFile(installPath, name, srcPath, Cp, deps)
}
-func (m *moduleContext) InstallExecutable(installPath OutputPath, name string, srcPath Path,
- deps ...Path) OutputPath {
+func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
+ deps ...Path) InstallPath {
return m.installFile(installPath, name, srcPath, CpExecutable, deps)
}
-func (m *moduleContext) installFile(installPath OutputPath, name string, srcPath Path,
- rule blueprint.Rule, deps []Path) OutputPath {
+func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path,
+ rule blueprint.Rule, deps []Path) InstallPath {
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, fullInstallPath, false)
@@ -1587,7 +1624,7 @@
return fullInstallPath
}
-func (m *moduleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath {
+func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
@@ -1616,7 +1653,7 @@
// installPath/name -> absPath where absPath might be a path that is available only at runtime
// (e.g. /apex/...)
-func (m *moduleContext) InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath {
+func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
diff --git a/android/mutator.go b/android/mutator.go
index 7b7859c..88ac521 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,6 +15,8 @@
package android
import (
+ "reflect"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -121,7 +123,7 @@
Rename(name string)
- CreateModule(ModuleFactory, ...interface{})
+ CreateModule(ModuleFactory, ...interface{}) Module
}
type topDownMutatorContext struct {
@@ -243,9 +245,25 @@
t.Module().base().commonProperties.DebugName = name
}
-func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) {
- inherited := []interface{}{&t.Module().base().commonProperties, &t.Module().base().variableProperties}
- t.bp.CreateModule(ModuleFactoryAdaptor(factory), append(inherited, props...)...)
+func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
+ inherited := []interface{}{&t.Module().base().commonProperties}
+ module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), append(inherited, props...)...).(Module)
+
+ if t.Module().base().variableProperties != nil && module.base().variableProperties != nil {
+ src := t.Module().base().variableProperties
+ dst := []interface{}{
+ module.base().variableProperties,
+ // Put an empty copy of the src properties into dst so that properties in src that are not in dst
+ // don't cause a "failed to find property to extend" error.
+ proptools.CloneEmptyProperties(reflect.ValueOf(src).Elem()).Interface(),
+ }
+ err := proptools.AppendMatchingProperties(dst, src, nil)
+ if err != nil {
+ panic(err)
+ }
+ }
+
+ return module
}
func (b *bottomUpMutatorContext) MutatorName() string {
diff --git a/android/notices.go b/android/notices.go
index 7b61d65..bf273b5 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -60,7 +60,7 @@
})
}
-func BuildNoticeOutput(ctx ModuleContext, installPath OutputPath, installFilename string,
+func BuildNoticeOutput(ctx ModuleContext, installPath InstallPath, installFilename string,
noticePaths []Path) NoticeOutputs {
// Merge all NOTICE files into one.
// TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
diff --git a/android/package_ctx.go b/android/package_ctx.go
index 00b99ff..548450e 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -104,7 +104,8 @@
}
// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config
-// argument to a Context that supports Config().
+// argument to a Context that supports Config(), and provides a default Pool if none is
+// specified.
func (p PackageContext) RuleFunc(name string,
f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
@@ -114,6 +115,11 @@
if len(ctx.errors) > 0 {
return params, ctx.errors[0]
}
+ if ctx.Config().UseGoma() && params.Pool == nil {
+ // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
+ // local parallelism value
+ params.Pool = localPool
+ }
return params, nil
}, argNames...)
}
@@ -234,10 +240,16 @@
})
}
-// AndroidStaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified
+// AndroidStaticRule is an alias for StaticRule.
func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams,
argNames ...string) blueprint.Rule {
- return p.AndroidRuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
+ return p.StaticRule(name, params, argNames...)
+}
+
+// StaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified.
+func (p PackageContext) StaticRule(name string, params blueprint.RuleParams,
+ argNames ...string) blueprint.Rule {
+ return p.RuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
return params
}, argNames...)
}
@@ -245,18 +257,6 @@
// AndroidGomaStaticRule wraps blueprint.StaticRule but uses goma's parallelism if goma is enabled
func (p PackageContext) AndroidGomaStaticRule(name string, params blueprint.RuleParams,
argNames ...string) blueprint.Rule {
- return p.StaticRule(name, params, argNames...)
-}
-
-func (p PackageContext) AndroidRuleFunc(name string,
- f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
- return p.RuleFunc(name, func(ctx PackageRuleContext) blueprint.RuleParams {
- params := f(ctx)
- if ctx.Config().UseGoma() && params.Pool == nil {
- // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
- // local parallelism value
- params.Pool = localPool
- }
- return params
- }, argNames...)
+ // bypass android.PackageContext.StaticRule so that Pool does not get set to local_pool.
+ return p.PackageContext.StaticRule(name, params, argNames...)
}
diff --git a/android/paths.go b/android/paths.go
index 0d64a61..8dbb086 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -44,8 +44,10 @@
BaseModuleContext
InstallInData() bool
+ InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
+ InstallInRoot() bool
InstallBypassMake() bool
}
@@ -791,7 +793,7 @@
return OptionalPathForPath(PathForSource(ctx, relPath))
}
-// OutputPath is a Path representing a file path rooted from the build directory
+// OutputPath is a Path representing an intermediates file path rooted from the build directory
type OutputPath struct {
basePath
}
@@ -819,17 +821,6 @@
return OutputPath{basePath{path, ctx.Config(), ""}}
}
-// pathForInstallInMakeDir is used by PathForModuleInstall when the module returns true
-// for InstallBypassMake to produce an OutputPath that installs to $OUT_DIR instead of
-// $OUT_DIR/soong.
-func pathForInstallInMakeDir(ctx PathContext, pathComponents ...string) OutputPath {
- path, err := validatePath(pathComponents...)
- if err != nil {
- reportPathError(ctx, err)
- }
- return OutputPath{basePath{"../" + path, ctx.Config(), ""}}
-}
-
// PathsForOutput returns Paths rooted from buildDir
func PathsForOutput(ctx PathContext, paths []string) WritablePaths {
ret := make(WritablePaths, len(paths))
@@ -845,10 +836,6 @@
return filepath.Join(p.config.buildDir, p.path)
}
-func (p OutputPath) RelPathString() string {
- return p.path
-}
-
// Join creates a new OutputPath with paths... joined with the current path. The
// provided paths... may not use '..' to escape from the current path.
func (p OutputPath) Join(ctx PathContext, paths ...string) OutputPath {
@@ -1117,9 +1104,44 @@
return ModuleResPath{PathForModuleOut(ctx, "res", p)}
}
+// InstallPath is a Path representing a installed file path rooted from the build directory
+type InstallPath struct {
+ basePath
+
+ baseDir string // "../" for Make paths to convert "out/soong" to "out", "" for Soong paths
+}
+
+func (p InstallPath) writablePath() {}
+
+func (p InstallPath) String() string {
+ return filepath.Join(p.config.buildDir, p.baseDir, p.path)
+}
+
+// Join creates a new InstallPath with paths... joined with the current path. The
+// provided paths... may not use '..' to escape from the current path.
+func (p InstallPath) Join(ctx PathContext, paths ...string) InstallPath {
+ path, err := validatePath(paths...)
+ if err != nil {
+ reportPathError(ctx, err)
+ }
+ return p.withRel(path)
+}
+
+func (p InstallPath) withRel(rel string) InstallPath {
+ p.basePath = p.basePath.withRel(rel)
+ return p
+}
+
+// ToMakePath returns a new InstallPath that points to Make's install directory instead of Soong's,
+// i.e. out/ instead of out/soong/.
+func (p InstallPath) ToMakePath() InstallPath {
+ p.baseDir = "../"
+ return p
+}
+
// PathForModuleInstall returns a Path representing the install path for the
// module appended with paths...
-func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) OutputPath {
+func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
var outPaths []string
if ctx.Device() {
partition := modulePartition(ctx)
@@ -1139,13 +1161,30 @@
outPaths = append([]string{"debug"}, outPaths...)
}
outPaths = append(outPaths, pathComponents...)
- if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
- return pathForInstallInMakeDir(ctx, outPaths...)
+
+ path, err := validatePath(outPaths...)
+ if err != nil {
+ reportPathError(ctx, err)
}
- return PathForOutput(ctx, outPaths...)
+
+ ret := InstallPath{basePath{path, ctx.Config(), ""}, ""}
+ if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
+ ret = ret.ToMakePath()
+ }
+
+ return ret
}
-func InstallPathToOnDevicePath(ctx PathContext, path OutputPath) string {
+func PathForNdkInstall(ctx PathContext, paths ...string) InstallPath {
+ paths = append([]string{"ndk"}, paths...)
+ path, err := validatePath(paths...)
+ if err != nil {
+ reportPathError(ctx, err)
+ }
+ return InstallPath{basePath{path, ctx.Config(), ""}, ""}
+}
+
+func InstallPathToOnDevicePath(ctx PathContext, path InstallPath) string {
rel := Rel(ctx, PathForOutput(ctx, "target", "product", ctx.Config().DeviceName()).String(), path.String())
return "/" + rel
@@ -1155,9 +1194,15 @@
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"
+ if ctx.InstallInRoot() {
+ partition = "recovery/root"
+ } else {
+ // the layout of recovery partion is the same as that of system partition
+ partition = "recovery/root/system"
+ }
} else if ctx.SocSpecific() {
partition = ctx.DeviceConfig().VendorPath()
} else if ctx.DeviceSpecific() {
@@ -1166,6 +1211,8 @@
partition = ctx.DeviceConfig().ProductPath()
} else if ctx.SystemExtSpecific() {
partition = ctx.DeviceConfig().SystemExtPath()
+ } else if ctx.InstallInRoot() {
+ partition = "root"
} else {
partition = "system"
}
diff --git a/android/paths_test.go b/android/paths_test.go
index f2996bf..2e67272 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -201,8 +201,10 @@
baseModuleContext
inData bool
+ inTestcases bool
inSanitizerDir bool
inRecovery bool
+ inRoot bool
}
func (moduleInstallPathContextImpl) Fs() pathtools.FileSystem {
@@ -219,6 +221,10 @@
return m.inData
}
+func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
+ return m.inTestcases
+}
+
func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
return m.inSanitizerDir
}
@@ -227,6 +233,10 @@
return m.inRecovery
}
+func (m moduleInstallPathContextImpl) InstallInRoot() bool {
+ return m.inRoot
+}
+
func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
return false
}
@@ -308,6 +318,40 @@
in: []string{"bin", "my_test"},
out: "target/product/test_device/system_ext/bin/my_test",
},
+ {
+ name: "root binary",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ target: deviceTarget,
+ },
+ inRoot: true,
+ },
+ in: []string{"my_test"},
+ out: "target/product/test_device/root/my_test",
+ },
+ {
+ name: "recovery binary",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ target: deviceTarget,
+ },
+ inRecovery: true,
+ },
+ in: []string{"bin/my_test"},
+ out: "target/product/test_device/recovery/root/system/bin/my_test",
+ },
+ {
+ name: "recovery root binary",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ target: deviceTarget,
+ },
+ inRecovery: true,
+ inRoot: true,
+ },
+ in: []string{"my_test"},
+ out: "target/product/test_device/recovery/root/my_test",
+ },
{
name: "system native test binary",
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index d29ed16..6c4813b 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -65,7 +65,7 @@
installDirBase string
// The base install location when soc_specific property is set to true, e.g. "firmware" for prebuilt_firmware.
socInstallDirBase string
- installDirPath OutputPath
+ installDirPath InstallPath
additionalDependencies *Paths
}
@@ -91,7 +91,7 @@
return PathForModuleSrc(ctx, String(p.properties.Src))
}
-func (p *PrebuiltEtc) InstallDirPath() OutputPath {
+func (p *PrebuiltEtc) InstallDirPath() InstallPath {
return p.installDirPath
}
@@ -158,7 +158,7 @@
ExtraEntries: []AndroidMkExtraEntriesFunc{
func(entries *AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_TAGS", "optional")
- entries.SetString("LOCAL_MODULE_PATH", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
+ entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
entries.SetString("LOCAL_UNINSTALLABLE_MODULE", strconv.FormatBool(!p.Installable()))
if p.additionalDependencies != nil {
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
index 0a2c7a4..f675ea3 100644
--- a/android/prebuilt_etc_test.go
+++ b/android/prebuilt_etc_test.go
@@ -182,9 +182,9 @@
`)
p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a_core").Module().(*PrebuiltEtc)
- expected := "target/product/test_device/system/usr/share/bar"
- if p.installDirPath.RelPathString() != expected {
- t.Errorf("expected %q, got %q", expected, p.installDirPath.RelPathString())
+ expected := buildDir + "/target/product/test_device/system/usr/share/bar"
+ if p.installDirPath.String() != expected {
+ t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
}
}
@@ -199,9 +199,9 @@
buildOS := BuildOs.String()
p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
- expected := filepath.Join("host", config.PrebuiltOS(), "usr", "share", "bar")
- if p.installDirPath.RelPathString() != expected {
- t.Errorf("expected %q, got %q", expected, p.installDirPath.RelPathString())
+ expected := filepath.Join(buildDir, "host", config.PrebuiltOS(), "usr", "share", "bar")
+ if p.installDirPath.String() != expected {
+ t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
}
}
@@ -214,14 +214,14 @@
`)
p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a_core").Module().(*PrebuiltEtc)
- expected := "target/product/test_device/system/fonts"
- if p.installDirPath.RelPathString() != expected {
- t.Errorf("expected %q, got %q", expected, p.installDirPath.RelPathString())
+ expected := buildDir + "/target/product/test_device/system/fonts"
+ if p.installDirPath.String() != expected {
+ t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
}
}
func TestPrebuiltFirmwareDirPath(t *testing.T) {
- targetPath := "target/product/test_device"
+ targetPath := buildDir + "/target/product/test_device"
tests := []struct {
description string
config string
@@ -249,7 +249,7 @@
t.Run(tt.description, func(t *testing.T) {
ctx, _ := testPrebuiltEtc(t, tt.config)
p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a_core").Module().(*PrebuiltEtc)
- if p.installDirPath.RelPathString() != tt.expectedPath {
+ if p.installDirPath.String() != tt.expectedPath {
t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath)
}
})
diff --git a/android/sh_binary.go b/android/sh_binary.go
index ba0c8be..6db9892 100644
--- a/android/sh_binary.go
+++ b/android/sh_binary.go
@@ -48,6 +48,9 @@
// Whether this module is directly installable to one of the partitions. Default: true.
Installable *bool
+
+ // install symlinks to the binary
+ Symlinks []string `android:"arch_variant"`
}
type TestProperties struct {
@@ -103,6 +106,10 @@
return s.properties.Installable == nil || Bool(s.properties.Installable)
}
+func (s *ShBinary) Symlinks() []string {
+ return s.properties.Symlinks
+}
+
func (s *ShBinary) GenerateAndroidBuildActions(ctx ModuleContext) {
s.sourceFilePath = PathForModuleSrc(ctx, String(s.properties.Src))
filename := String(s.properties.Filename)
@@ -145,6 +152,9 @@
entries.SetString("LOCAL_MODULE_RELATIVE_PATH", String(s.properties.Sub_dir))
entries.SetString("LOCAL_MODULE_SUFFIX", "")
entries.SetString("LOCAL_MODULE_STEM", s.outputFilePath.Rel())
+ if len(s.properties.Symlinks) > 0 {
+ entries.SetString("LOCAL_MODULE_SYMLINKS", strings.Join(s.properties.Symlinks, " "))
+ }
}
func (s *ShTest) GenerateAndroidBuildActions(ctx ModuleContext) {
diff --git a/android/singleton.go b/android/singleton.go
index a59d54a..7f9c216 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -127,6 +127,11 @@
}
func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule {
+ if s.Config().UseGoma() && params.Pool == nil {
+ // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
+ // local parallelism value
+ params.Pool = localPool
+ }
rule := s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...)
if s.Config().captureBuild {
s.ruleParams[rule] = params
diff --git a/android/variable.go b/android/variable.go
index 3f2b9e9..41943b0 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -122,7 +122,7 @@
} `android:"arch_variant"`
}
-var zeroProductVariables variableProperties
+var zeroProductVariables interface{} = variableProperties{}
type productVariables struct {
// Suffix to add to generated Makefiles
@@ -366,8 +366,13 @@
// TODO: depend on config variable, create variants, propagate variants up tree
a := module.base()
- variableValues := reflect.ValueOf(&a.variableProperties.Product_variables).Elem()
- zeroValues := reflect.ValueOf(zeroProductVariables.Product_variables)
+
+ if a.variableProperties == nil {
+ return
+ }
+
+ variableValues := reflect.ValueOf(a.variableProperties).Elem().FieldByName("Product_variables")
+ zeroValues := reflect.ValueOf(zeroProductVariables).FieldByName("Product_variables")
for i := 0; i < variableValues.NumField(); i++ {
variableValue := variableValues.Field(i)
@@ -496,3 +501,106 @@
return nil
}
+
+var variablePropTypeMap OncePer
+
+// sliceToTypeArray takes a slice of property structs and returns a reflection created array containing the
+// reflect.Types of each property struct. The result can be used as a key in a map.
+func sliceToTypeArray(s []interface{}) interface{} {
+ // Create an array using reflection whose length is the length of the input slice
+ ret := reflect.New(reflect.ArrayOf(len(s), reflect.TypeOf(reflect.TypeOf(0)))).Elem()
+ for i, e := range s {
+ ret.Index(i).Set(reflect.ValueOf(reflect.TypeOf(e)))
+ }
+ return ret.Interface()
+}
+
+// createVariableProperties takes the list of property structs for a module and returns a property struct that
+// contains the product variable properties that exist in the property structs, or nil if there are none. It
+// caches the result.
+func createVariableProperties(moduleTypeProps []interface{}, productVariables interface{}) interface{} {
+ // Convert the moduleTypeProps to an array of reflect.Types that can be used as a key in the OncePer.
+ key := sliceToTypeArray(moduleTypeProps)
+
+ // Use the variablePropTypeMap OncePer to cache the result for each set of property struct types.
+ typ, _ := variablePropTypeMap.Once(NewCustomOnceKey(key), func() interface{} {
+ // Compute the filtered property struct type.
+ return createVariablePropertiesType(moduleTypeProps, productVariables)
+ }).(reflect.Type)
+
+ if typ == nil {
+ return nil
+ }
+
+ // Create a new pointer to a filtered property struct.
+ return reflect.New(typ).Interface()
+}
+
+// createVariablePropertiesType creates a new type that contains only the product variable properties that exist in
+// a list of property structs.
+func createVariablePropertiesType(moduleTypeProps []interface{}, productVariables interface{}) reflect.Type {
+ typ, _ := proptools.FilterPropertyStruct(reflect.TypeOf(productVariables),
+ func(field reflect.StructField, prefix string) (bool, reflect.StructField) {
+ // Filter function, returns true if the field should be in the resulting struct
+ if prefix == "" {
+ // Keep the top level Product_variables field
+ return true, field
+ }
+ _, rest := splitPrefix(prefix)
+ if rest == "" {
+ // Keep the 2nd level field (i.e. Product_variables.Eng)
+ return true, field
+ }
+
+ // Strip off the first 2 levels of the prefix
+ _, prefix = splitPrefix(rest)
+
+ for _, p := range moduleTypeProps {
+ if fieldExistsByNameRecursive(reflect.TypeOf(p).Elem(), prefix, field.Name) {
+ // Keep any fields that exist in one of the property structs
+ return true, field
+ }
+ }
+
+ return false, field
+ })
+ return typ
+}
+
+func splitPrefix(prefix string) (first, rest string) {
+ index := strings.IndexByte(prefix, '.')
+ if index == -1 {
+ return prefix, ""
+ }
+ return prefix[:index], prefix[index+1:]
+}
+
+func fieldExistsByNameRecursive(t reflect.Type, prefix, name string) bool {
+ if t.Kind() != reflect.Struct {
+ panic(fmt.Errorf("fieldExistsByNameRecursive can only be called on a reflect.Struct"))
+ }
+
+ if prefix != "" {
+ split := strings.SplitN(prefix, ".", 2)
+ firstPrefix := split[0]
+ rest := ""
+ if len(split) > 1 {
+ rest = split[1]
+ }
+ f, exists := t.FieldByName(firstPrefix)
+ if !exists {
+ return false
+ }
+ ft := f.Type
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ if ft.Kind() != reflect.Struct {
+ panic(fmt.Errorf("field %q in %q is not a struct", firstPrefix, t))
+ }
+ return fieldExistsByNameRecursive(ft, rest, name)
+ } else {
+ _, exists := t.FieldByName(name)
+ return exists
+ }
+}
diff --git a/android/variable_test.go b/android/variable_test.go
index ce9ba54..c1910fe 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -16,7 +16,10 @@
import (
"reflect"
+ "strconv"
"testing"
+
+ "github.com/google/blueprint/proptools"
)
type printfIntoPropertyTestCase struct {
@@ -122,3 +125,111 @@
}
}
}
+
+type testProductVariableModule struct {
+ ModuleBase
+}
+
+func (m *testProductVariableModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+var testProductVariableProperties = struct {
+ Product_variables struct {
+ Eng struct {
+ Srcs []string
+ Cflags []string
+ }
+ }
+}{}
+
+func testProductVariableModuleFactoryFactory(props interface{}) func() Module {
+ return func() Module {
+ m := &testProductVariableModule{}
+ clonedProps := proptools.CloneProperties(reflect.ValueOf(props)).Interface()
+ m.AddProperties(clonedProps)
+
+ // Set a default variableProperties, this will be used as the input to the property struct filter
+ // for this test module.
+ m.variableProperties = testProductVariableProperties
+ InitAndroidModule(m)
+ return m
+ }
+}
+
+func TestProductVariables(t *testing.T) {
+ ctx := NewTestContext()
+ // A module type that has a srcs property but not a cflags property.
+ ctx.RegisterModuleType("module1", ModuleFactoryAdaptor(testProductVariableModuleFactoryFactory(struct {
+ Srcs []string
+ }{})))
+ // A module type that has a cflags property but not a srcs property.
+ ctx.RegisterModuleType("module2", ModuleFactoryAdaptor(testProductVariableModuleFactoryFactory(struct {
+ Cflags []string
+ }{})))
+ // A module type that does not have any properties that match product_variables.
+ ctx.RegisterModuleType("module3", ModuleFactoryAdaptor(testProductVariableModuleFactoryFactory(struct {
+ Foo []string
+ }{})))
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("variable", variableMutator).Parallel()
+ })
+
+ // Test that a module can use one product variable even if it doesn't have all the properties
+ // supported by that product variable.
+ bp := `
+ module1 {
+ name: "foo",
+ product_variables: {
+ eng: {
+ srcs: ["foo.c"],
+ },
+ },
+ }
+ module2 {
+ name: "bar",
+ product_variables: {
+ eng: {
+ cflags: ["-DBAR"],
+ },
+ },
+ }
+
+ module3 {
+ name: "baz",
+ }
+ `
+
+ mockFS := map[string][]byte{
+ "Android.bp": []byte(bp),
+ }
+
+ ctx.MockFileSystem(mockFS)
+
+ ctx.Register()
+
+ config := TestConfig(buildDir, nil)
+ config.TestProductVariables.Eng = proptools.BoolPtr(true)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+}
+
+func BenchmarkSliceToTypeArray(b *testing.B) {
+ for _, n := range []int{1, 2, 4, 8, 100} {
+ var propStructs []interface{}
+ for i := 0; i < n; i++ {
+ propStructs = append(propStructs, &struct {
+ A *string
+ B string
+ }{})
+
+ }
+ b.Run(strconv.Itoa(n), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ _ = sliceToTypeArray(propStructs)
+ }
+ })
+ }
+}
diff --git a/apex/apex.go b/apex/apex.go
index 8891094..5f71425 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -152,7 +152,6 @@
var (
whitelistNoApex = map[string][]string{
"apex_test_build_features": []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"},
@@ -223,12 +222,14 @@
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())
+
+ vndkVersion := proptools.String(ab.vndkProperties.Vndk_version)
+
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())
+ mctx.PropertyErrorf("vndk_version", "%v is already defined in %q", vndkVersion, other.BaseModuleName())
}
vndkApexList[vndkVersion] = ab
}
@@ -562,8 +563,8 @@
bundleModuleFile android.WritablePath
outputFiles map[apexPackaging]android.WritablePath
- flattenedOutput android.OutputPath
- installDir android.OutputPath
+ flattenedOutput android.InstallPath
+ installDir android.InstallPath
prebuiltFileToDelete string
@@ -868,9 +869,7 @@
dirInApex = "lib64"
}
dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
- if !ccMod.Arch().Native {
- dirInApex = filepath.Join(dirInApex, ccMod.Arch().ArchType.String())
- } else if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
+ if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
}
if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), config) {
@@ -893,9 +892,7 @@
func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
dirInApex = filepath.Join("bin", cc.RelativeInstallPath())
- if !cc.Arch().Native {
- dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
- } else if cc.Target().NativeBridge == android.NativeBridgeEnabled {
+ if cc.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
}
fileToCopy = cc.OutputFile().Path()
@@ -1036,7 +1033,7 @@
return true
} else if sh, ok := child.(*android.ShBinary); ok {
fileToCopy, dirInApex := getCopyManifestForShBinary(sh)
- filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, shBinary, sh, nil})
+ filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, shBinary, sh, sh.Symlinks()})
} else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
fileToCopy, dirInApex := getCopyManifestForPyBinary(py)
filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, pyBinary, py, nil})
@@ -1216,6 +1213,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 {
@@ -1616,8 +1623,8 @@
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))
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join(a.installDir.ToMakePath().String(),
+ name, fi.installDir))
if !a.isFlattenedVariant() {
fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
}
@@ -1726,7 +1733,7 @@
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFiles[apexType].String())
- fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String())
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix())
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
if len(moduleNames) > 0 {
@@ -1737,7 +1744,7 @@
}
if a.prebuiltFileToDelete != "" {
fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", "rm -rf "+
- filepath.Join("$(OUT_DIR)", a.installDir.RelPathString(), a.prebuiltFileToDelete))
+ filepath.Join(a.installDir.ToMakePath().String(), a.prebuiltFileToDelete))
}
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
@@ -1792,6 +1799,15 @@
}{
proptools.StringPtr("both"),
})
+
+ vndkVersion := proptools.StringDefault(bundle.vndkProperties.Vndk_version, "current")
+ if vndkVersion == "current" {
+ vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
+ bundle.vndkProperties.Vndk_version = proptools.StringPtr(vndkVersion)
+ }
+
+ // Ensure VNDK APEX mount point is formatted as com.android.vndk.v###
+ bundle.properties.Apex_name = proptools.StringPtr("com.android.vndk.v" + vndkVersion)
})
return bundle
}
@@ -1831,7 +1847,7 @@
properties PrebuiltProperties
inputApex android.Path
- installDir android.OutputPath
+ installDir android.InstallPath
installFilename string
outputApex android.WritablePath
}
@@ -1978,7 +1994,7 @@
Include: "$(BUILD_PREBUILT)",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", filepath.Join("$(OUT_DIR)", p.installDir.RelPathString()))
+ entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String())
entries.SetString("LOCAL_MODULE_STEM", p.installFilename)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", p.properties.Overrides...)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 114d89f..ddf0459 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1382,6 +1382,7 @@
vndk: {
enabled: true,
},
+ target_arch: "arm64",
srcs: ["libvndk27.so"],
}
`, withFiles(map[string][]byte{
@@ -1441,6 +1442,37 @@
}))
}
+func TestVndkApexNameRule(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex_vndk {
+ name: "myapex",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ }
+ apex_vndk {
+ name: "myapex_v28",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ vndk_version: "28",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }`)
+
+ assertApexName := func(expected, moduleName string) {
+ bundle := ctx.ModuleForTests(moduleName, "android_common_"+moduleName).Module().(*apexBundle)
+ actual := proptools.String(bundle.properties.Apex_name)
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("Got '%v', expected '%v'", actual, expected)
+ }
+ }
+
+ assertApexName("com.android.vndk.vVER", "myapex")
+ assertApexName("com.android.vndk.v28", "myapex_v28")
+}
+
func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
ctx, _ := testApex(t, `
apex_vndk {
@@ -1469,10 +1501,10 @@
}
`, 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"},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm64", NativeBridgeRelativePath: "x86_64"},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm", NativeBridgeRelativePath: "x86"},
},
}))
@@ -1864,8 +1896,8 @@
`)
apex := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
- expected := "target/product/test_device/product/apex"
- actual := apex.installDir.RelPathString()
+ expected := buildDir + "/target/product/test_device/product/apex"
+ actual := apex.installDir.String()
if actual != expected {
t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
}
@@ -2422,6 +2454,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/cc/androidmk.go b/cc/androidmk.go
index aab4edd..f1d329f 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -350,11 +350,10 @@
}
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- path := installer.path.RelPathString()
- dir, file := filepath.Split(path)
+ path, file := filepath.Split(installer.path.ToMakePath().String())
stem, suffix, _ := android.SplitFileExt(file)
fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
})
}
@@ -395,12 +394,11 @@
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
c.libraryDecorator.androidMkWriteExportedFlags(w)
- path := c.path.RelPathString()
- dir, file := filepath.Split(path)
+ path, file := filepath.Split(c.path.ToMakePath().String())
stem, suffix, ext := android.SplitFileExt(file)
fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
})
}
diff --git a/cc/binary.go b/cc/binary.go
index 0d69405..9f18d6c 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -453,7 +453,7 @@
// Bionic binaries (e.g. linker) is installed to the bootstrap subdirectory.
// The original path becomes a symlink to the corresponding file in the
// runtime APEX.
- translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled || !ctx.Arch().Native
+ translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexName() == "" && !ctx.inRecovery() {
if ctx.Device() && isBionic(ctx.baseModuleName()) {
binary.installSymlinkToRuntimeApex(ctx, file)
diff --git a/cc/builder.go b/cc/builder.go
index c4f65da..0760dd4 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -195,7 +195,7 @@
_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
- sAbiDiff = pctx.AndroidRuleFunc("sAbiDiff",
+ sAbiDiff = pctx.RuleFunc("sAbiDiff",
func(ctx android.PackageRuleContext) blueprint.RuleParams {
// TODO(b/78139997): Add -check-all-apis back
commandStr := "($sAbiDiffer ${allowFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
diff --git a/cc/cc.go b/cc/cc.go
index 744e0cb..0f2cb4c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2208,6 +2208,8 @@
&BaseLinkerProperties{},
&ObjectLinkerProperties{},
&LibraryProperties{},
+ &StaticProperties{},
+ &SharedProperties{},
&FlagExporterProperties{},
&BinaryLinkerProperties{},
&TestProperties{},
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 6275822..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)
}
@@ -2321,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 e59aa37..71bea42 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -163,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/fuzz.go b/cc/fuzz.go
index 7806e83..c19fdc5 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -16,8 +16,8 @@
import (
"path/filepath"
+ "strings"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -161,6 +161,7 @@
// 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 {
@@ -220,15 +221,12 @@
}
})
- // List of architecture + host/device specific packages to build via. 'make fuzz'.
- var archDirTargets android.Paths
-
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")
- archDirTargets = append(archDirTargets, outputFile)
+ s.packages = append(s.packages, outputFile)
command := builder.Command().BuiltTool(ctx, "soong_zip").
Flag("-j").
@@ -242,11 +240,12 @@
builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
"Create fuzz target packages for "+arch+"-"+hostOrTarget)
}
+}
- ctx.Build(pctx, android.BuildParams{
- Rule: blueprint.Phony,
- Output: android.PathForPhony(ctx, "fuzz"),
- Implicits: archDirTargets,
- Description: "Build all Android fuzz targets, and create packages.",
- })
+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/installer.go b/cc/installer.go
index a52ccf1..9fdc88a 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -52,7 +52,7 @@
relative string
location installLocation
- path android.OutputPath
+ path android.InstallPath
}
var _ installer = (*baseInstaller)(nil)
@@ -61,16 +61,15 @@
return []interface{}{&installer.Properties}
}
-func (installer *baseInstaller) installDir(ctx ModuleContext) android.OutputPath {
+func (installer *baseInstaller) installDir(ctx ModuleContext) android.InstallPath {
dir := installer.dir
if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
dir = installer.dir64
}
- if !ctx.Host() && !ctx.Arch().Native {
- dir = filepath.Join(dir, ctx.Arch().ArchType.String())
- }
if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath)
+ } else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
+ dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
if installer.location == InstallInData && ctx.useVndk() {
dir = filepath.Join(dir, "vendor")
diff --git a/cc/library.go b/cc/library.go
index c402ea0..0fb3c78 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)
@@ -775,9 +791,7 @@
// Optimize out relinking against shared libraries whose interface hasn't changed by
// depending on a table of contents file instead of the library itself.
- tocPath := outputFile.RelPathString()
- tocPath = pathtools.ReplaceExtension(tocPath, flags.Toolchain.ShlibSuffix()[1:]+".toc")
- tocFile := android.PathForOutput(ctx, tocPath)
+ tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
library.tocFile = android.OptionalPathForPath(tocFile)
TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
@@ -978,11 +992,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 {
@@ -1032,7 +1048,7 @@
// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
// The original path becomes a symlink to the corresponding file in the
// runtime APEX.
- translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled || !ctx.Arch().Native
+ translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() && !translatedArch && !ctx.inRecovery() {
if ctx.Device() {
library.installSymlinkToRuntimeApex(ctx, file)
@@ -1166,16 +1182,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 +1349,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/ndk_headers.go b/cc/ndk_headers.go
index 4065128..b8423be 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -48,7 +48,7 @@
}
// Returns the NDK base include path for use with sdk_version current. Usable with -I.
-func getCurrentIncludePath(ctx android.ModuleContext) android.OutputPath {
+func getCurrentIncludePath(ctx android.ModuleContext) android.InstallPath {
return getNdkSysrootBase(ctx).Join(ctx, "usr/include")
}
@@ -94,7 +94,7 @@
}
func getHeaderInstallDir(ctx android.ModuleContext, header android.Path, from string,
- to string) android.OutputPath {
+ to string) android.InstallPath {
// Output path is the sysroot base + "usr/include" + to directory + directory component
// of the file without the leading from directory stripped.
//
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index e39bae5..f6de4ef 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -66,12 +66,12 @@
pctx.Import("android/soong/android")
}
-func getNdkInstallBase(ctx android.PathContext) android.OutputPath {
- return android.PathForOutput(ctx, "ndk")
+func getNdkInstallBase(ctx android.PathContext) android.InstallPath {
+ return android.PathForNdkInstall(ctx)
}
// Returns the main install directory for the NDK sysroot. Usable with --sysroot.
-func getNdkSysrootBase(ctx android.PathContext) android.OutputPath {
+func getNdkSysrootBase(ctx android.PathContext) android.InstallPath {
return getNdkInstallBase(ctx).Join(ctx, "sysroot")
}
diff --git a/cc/stl.go b/cc/stl.go
index 458129c..aa34240 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -221,13 +221,13 @@
if !ctx.toolchain().Bionic() {
flags.CppFlags = append(flags.CppFlags, "-nostdinc++")
- flags.extraLibFlags = append(flags.extraLibFlags, "-nodefaultlibs")
- if ctx.staticBinary() {
- flags.extraLibFlags = append(flags.extraLibFlags, hostStaticGccLibs[ctx.Os()]...)
- } else {
- flags.extraLibFlags = append(flags.extraLibFlags, hostDynamicGccLibs[ctx.Os()]...)
- }
+ flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++")
if ctx.Windows() {
+ if stl.Properties.SelectedStl == "libc++_static" {
+ // These are transitively needed by libc++_static.
+ flags.extraLibFlags = append(flags.extraLibFlags,
+ "-lmsvcrt", "-lucrt")
+ }
// Use SjLj exceptions for 32-bit. libgcc_eh implements SjLj
// exception model for 32-bit.
if ctx.Arch().ArchType == android.X86 {
@@ -260,12 +260,7 @@
// None or error.
if !ctx.toolchain().Bionic() {
flags.CppFlags = append(flags.CppFlags, "-nostdinc++")
- flags.extraLibFlags = append(flags.extraLibFlags, "-nodefaultlibs")
- if ctx.staticBinary() {
- flags.extraLibFlags = append(flags.extraLibFlags, hostStaticGccLibs[ctx.Os()]...)
- } else {
- flags.extraLibFlags = append(flags.extraLibFlags, hostDynamicGccLibs[ctx.Os()]...)
- }
+ flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++")
}
default:
panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
@@ -273,22 +268,3 @@
return flags
}
-
-var hostDynamicGccLibs, hostStaticGccLibs map[android.OsType][]string
-
-func init() {
- hostDynamicGccLibs = map[android.OsType][]string{
- android.Fuchsia: []string{"-lc", "-lunwind"},
- android.Linux: []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"},
- android.Darwin: []string{"-lc", "-lSystem"},
- android.Windows: []string{"-Wl,--start-group", "-lmingw32", "-lgcc", "-lgcc_eh",
- "-lmoldname", "-lmingwex", "-lmsvcrt", "-lucrt", "-lpthread",
- "-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lpsapi",
- "-Wl,--end-group"},
- }
- hostStaticGccLibs = map[android.OsType][]string{
- android.Linux: []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"},
- android.Darwin: []string{"NO_STATIC_HOST_BINARIES_ON_DARWIN"},
- android.Windows: []string{"NO_STATIC_HOST_BINARIES_ON_WINDOWS"},
- }
-}
diff --git a/cc/testing.go b/cc/testing.go
index a0b1634..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))
@@ -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_prebuilt.go b/cc/vndk_prebuilt.go
index 8126e4a..2cebb6d 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -129,6 +129,18 @@
func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
+
+ arches := ctx.DeviceConfig().Arches()
+ if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
+ ctx.Module().SkipInstall()
+ return nil
+ }
+
+ if ctx.DeviceConfig().BinderBitness() != p.binderBit() {
+ ctx.Module().SkipInstall()
+ return nil
+ }
+
if len(p.properties.Srcs) > 0 && p.shared() {
p.libraryDecorator.exportIncludes(ctx)
p.libraryDecorator.reexportSystemDirs(p.properties.Export_system_include_dirs...)
@@ -136,6 +148,8 @@
// current VNDK prebuilts are only shared libs.
return p.singleSourcePath(ctx)
}
+
+ ctx.Module().SkipInstall()
return nil
}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index c378f09..40644a3 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -248,7 +248,7 @@
odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex"))
odexInstallPath := toOdexPath(module.DexLocation)
if odexOnSystemOther(module, global) {
- odexInstallPath = strings.Replace(odexInstallPath, SystemPartition, SystemOtherPartition, 1)
+ odexInstallPath = filepath.Join(SystemOtherPartition, odexInstallPath)
}
vdexPath := odexPath.ReplaceExtension(ctx, "vdex")
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 7f1fe42..aca5e63 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/system"},
+ {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/system"},
+ {module: systemProductModule, expectedPartition: "system_other/system/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/java/androidmk.go b/java/androidmk.go
index 032dc6a..bc61297 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -329,7 +329,8 @@
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"
+ install := app.onDeviceDir + "/" +
+ strings.TrimSuffix(app.installApkName, ".apk") + "_" + split.suffix + ".apk"
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", split.path.String()+":"+install)
}
},
diff --git a/java/app.go b/java/app.go
index afddb6a..e033661 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.InstallPath
+
+ 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 {
@@ -764,7 +773,7 @@
usesLibrary usesLibrary
- installPath android.OutputPath
+ installPath android.InstallPath
}
type AndroidAppImportProperties struct {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 6214dac..b48871e 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -22,7 +22,7 @@
type dexpreopter struct {
dexpreoptProperties DexpreoptProperties
- installPath android.OutputPath
+ installPath android.InstallPath
uncompressedDex bool
isSDKLibrary bool
isTest bool
@@ -94,7 +94,7 @@
return false
}
-func odexOnSystemOther(ctx android.ModuleContext, installPath android.OutputPath) bool {
+func odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool {
return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreoptGlobalConfig(ctx))
}
@@ -126,10 +126,6 @@
archs = archs[:1]
}
}
- if ctx.Config().SecondArchIsTranslated() {
- // Only preopt primary arch for translated arch since there is only an image there.
- archs = archs[:1]
- }
var images android.Paths
var imagesDeps []android.Paths
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 8c699b8..043f9da 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -87,11 +87,7 @@
// supported through native bridge.
func dexpreoptTargets(ctx android.PathContext) []android.Target {
var targets []android.Target
- for i, target := range ctx.Config().Targets[android.Android] {
- if ctx.Config().SecondArchIsTranslated() && i > 0 {
- break
- }
-
+ for _, target := range ctx.Config().Targets[android.Android] {
if target.NativeBridge == android.NativeBridgeDisabled {
targets = append(targets, target)
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 1d5331e..aab61c5 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -461,14 +461,14 @@
flags droiddocBuilderFlags) android.Paths {
outSrcFiles := make(android.Paths, 0, len(srcFiles))
+ var aidlSrcs android.Paths
aidlIncludeFlags := genAidlIncludeFlags(srcFiles)
for _, srcFile := range srcFiles {
switch srcFile.Ext() {
case ".aidl":
- javaFile := genAidl(ctx, srcFile, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
- outSrcFiles = append(outSrcFiles, javaFile)
+ aidlSrcs = append(aidlSrcs, srcFile)
case ".logtags":
javaFile := genLogtags(ctx, srcFile)
outSrcFiles = append(outSrcFiles, javaFile)
@@ -477,6 +477,12 @@
}
}
+ // Process all aidl files together to support sharding them into one or more rules that produce srcjars.
+ if len(aidlSrcs) > 0 {
+ srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
+ outSrcFiles = append(outSrcFiles, srcJarFiles...)
+ }
+
return outSrcFiles
}
diff --git a/java/gen.go b/java/gen.go
index b840b60..d50a665 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -15,9 +15,11 @@
package java
import (
+ "strconv"
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/pathtools"
"android/soong/android"
)
@@ -29,13 +31,6 @@
}
var (
- aidl = pctx.AndroidStaticRule("aidl",
- blueprint.RuleParams{
- Command: "${config.AidlCmd} -d$depFile $aidlFlags $in $out",
- CommandDeps: []string{"${config.AidlCmd}"},
- },
- "depFile", "aidlFlags")
-
logtags = pctx.AndroidStaticRule("logtags",
blueprint.RuleParams{
Command: "$logtagsCmd -o $out $in",
@@ -49,23 +44,64 @@
})
)
-func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path {
- javaFile := android.GenPathWithExt(ctx, "aidl", aidlFile, "java")
- depFile := javaFile.String() + ".d"
+func genAidl(ctx android.ModuleContext, aidlFiles android.Paths, aidlFlags string, deps android.Paths) android.Paths {
+ // Shard aidl files into groups of 50 to avoid having to recompile all of them if one changes and to avoid
+ // hitting command line length limits.
+ shards := android.ShardPaths(aidlFiles, 50)
- ctx.Build(pctx, android.BuildParams{
- Rule: aidl,
- Description: "aidl " + aidlFile.Rel(),
- Output: javaFile,
- Input: aidlFile,
- Implicits: deps,
- Args: map[string]string{
- "depFile": depFile,
- "aidlFlags": aidlFlags,
- },
- })
+ srcJarFiles := make(android.Paths, 0, len(shards))
- return javaFile
+ for i, shard := range shards {
+ srcJarFile := android.PathForModuleGen(ctx, "aidl", "aidl"+strconv.Itoa(i)+".srcjar")
+ srcJarFiles = append(srcJarFiles, srcJarFile)
+
+ outDir := srcJarFile.ReplaceExtension(ctx, "tmp")
+
+ rule := android.NewRuleBuilder()
+
+ rule.Command().Text("rm -rf").Flag(outDir.String())
+ rule.Command().Text("mkdir -p").Flag(outDir.String())
+ rule.Command().Text("FLAGS=' " + aidlFlags + "'")
+
+ for _, aidlFile := range shard {
+ depFile := srcJarFile.InSameDir(ctx, aidlFile.String()+".d")
+ javaFile := outDir.Join(ctx, pathtools.ReplaceExtension(aidlFile.String(), "java"))
+ rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "aidl")).
+ FlagWithDepFile("-d", depFile).
+ Flag("$FLAGS").
+ Input(aidlFile).
+ Output(javaFile).
+ Implicits(deps)
+ rule.Temporary(javaFile)
+ }
+
+ rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
+ // TODO(b/124333557): this can't use -srcjar for now, aidl on parcelables generates java files
+ // without a package statement, which causes -srcjar to put them in the top level of the zip file.
+ // Once aidl skips parcelables we can use -srcjar.
+ //Flag("-srcjar").
+ Flag("-write_if_changed").
+ FlagWithOutput("-o ", srcJarFile).
+ FlagWithArg("-C ", outDir.String()).
+ FlagWithArg("-D ", outDir.String())
+
+ rule.Command().Text("rm -rf").Flag(outDir.String())
+
+ rule.Restat()
+
+ ruleName := "aidl"
+ ruleDesc := "aidl"
+ if len(shards) > 1 {
+ ruleName += "_" + strconv.Itoa(i)
+ ruleDesc += " " + strconv.Itoa(i)
+ }
+
+ rule.Build(pctx, ctx, ruleName, ruleDesc)
+ }
+
+ return srcJarFiles
}
func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Path {
@@ -98,26 +134,38 @@
flags javaBuilderFlags) android.Paths {
outSrcFiles := make(android.Paths, 0, len(srcFiles))
+ var protoSrcs android.Paths
+ var aidlSrcs android.Paths
aidlIncludeFlags := genAidlIncludeFlags(srcFiles)
for _, srcFile := range srcFiles {
switch srcFile.Ext() {
case ".aidl":
- javaFile := genAidl(ctx, srcFile, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
- outSrcFiles = append(outSrcFiles, javaFile)
+ aidlSrcs = append(aidlSrcs, srcFile)
case ".logtags":
j.logtagsSrcs = append(j.logtagsSrcs, srcFile)
javaFile := genLogtags(ctx, srcFile)
outSrcFiles = append(outSrcFiles, javaFile)
case ".proto":
- srcJarFile := genProto(ctx, srcFile, flags.proto)
- outSrcFiles = append(outSrcFiles, srcJarFile)
+ protoSrcs = append(protoSrcs, srcFile)
default:
outSrcFiles = append(outSrcFiles, srcFile)
}
}
+ // Process all proto files together to support sharding them into one or more rules that produce srcjars.
+ if len(protoSrcs) > 0 {
+ srcJarFiles := genProto(ctx, protoSrcs, flags.proto)
+ outSrcFiles = append(outSrcFiles, srcJarFiles...)
+ }
+
+ // Process all aidl files together to support sharding them into one or more rules that produce srcjars.
+ if len(aidlSrcs) > 0 {
+ srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
+ outSrcFiles = append(outSrcFiles, srcJarFiles...)
+ }
+
return outSrcFiles
}
diff --git a/java/java.go b/java/java.go
index f7b0f53..4264ba9 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1795,7 +1795,7 @@
isWrapperVariant bool
wrapperFile android.Path
- binaryFile android.OutputPath
+ binaryFile android.InstallPath
}
func (j *Binary) HostToolPath() android.OptionalPath {
diff --git a/java/java_test.go b/java/java_test.go
index a932319..f0cb6f8 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -18,6 +18,7 @@
"io/ioutil"
"os"
"path/filepath"
+ "reflect"
"strconv"
"strings"
"testing"
@@ -811,19 +812,22 @@
}
`)
- inputs := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc").Inputs
+ barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc")
var javaSrcs []string
- for _, i := range inputs {
+ for _, i := range barDoc.Inputs {
javaSrcs = append(javaSrcs, i.Base())
}
- if len(javaSrcs) != 3 || javaSrcs[0] != "a.java" || javaSrcs[1] != "IFoo.java" || javaSrcs[2] != "IBar.java" {
- t.Errorf("inputs of bar-doc must be []string{\"a.java\", \"IFoo.java\", \"IBar.java\", but was %#v.", javaSrcs)
+ if len(javaSrcs) != 1 || javaSrcs[0] != "a.java" {
+ t.Errorf("inputs of bar-doc must be []string{\"a.java\"}, but was %#v.", javaSrcs)
}
- aidlRule := ctx.ModuleForTests("bar-doc", "android_common").Output(inputs[2].String())
- aidlFlags := aidlRule.Args["aidlFlags"]
- if !strings.Contains(aidlFlags, "-Ibar-doc") {
- t.Errorf("aidl flags for IBar.aidl should contain \"-Ibar-doc\", but was %q", aidlFlags)
+ aidl := ctx.ModuleForTests("bar-doc", "android_common").Rule("aidl")
+ if g, w := barDoc.Implicits.Strings(), aidl.Output.String(); !inList(w, g) {
+ t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
+ }
+
+ if g, w := aidl.Implicits.Strings(), []string{"bar-doc/IBar.aidl", "bar-doc/IFoo.aidl"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("aidl inputs must be %q, but was %q", w, g)
}
}
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 3d46077..23ba2b0 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -30,7 +30,7 @@
android.ModuleBase
properties platformCompatConfigProperties
- installDirPath android.OutputPath
+ installDirPath android.InstallPath
configFile android.OutputPath
}
@@ -78,7 +78,7 @@
Include: "$(BUILD_PREBUILT)",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
+ entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.configFile.Base())
},
},
diff --git a/java/proto.go b/java/proto.go
index f5c233c..e013bb4 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -15,36 +15,61 @@
package java
import (
+ "path/filepath"
+ "strconv"
+
"android/soong/android"
)
-func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags) android.Path {
- srcJarFile := android.GenPathWithExt(ctx, "proto", protoFile, "srcjar")
+func genProto(ctx android.ModuleContext, protoFiles android.Paths, flags android.ProtoFlags) android.Paths {
+ // Shard proto files into groups of 100 to avoid having to recompile all of them if one changes and to avoid
+ // hitting command line length limits.
+ shards := android.ShardPaths(protoFiles, 100)
- outDir := srcJarFile.ReplaceExtension(ctx, "tmp")
- depFile := srcJarFile.ReplaceExtension(ctx, "srcjar.d")
+ srcJarFiles := make(android.Paths, 0, len(shards))
- rule := android.NewRuleBuilder()
+ for i, shard := range shards {
+ srcJarFile := android.PathForModuleGen(ctx, "proto", "proto"+strconv.Itoa(i)+".srcjar")
+ srcJarFiles = append(srcJarFiles, srcJarFile)
- rule.Command().Text("rm -rf").Flag(outDir.String())
- rule.Command().Text("mkdir -p").Flag(outDir.String())
+ outDir := srcJarFile.ReplaceExtension(ctx, "tmp")
- android.ProtoRule(ctx, rule, protoFile, flags, flags.Deps, outDir, depFile, nil)
+ rule := android.NewRuleBuilder()
- // Proto generated java files have an unknown package name in the path, so package the entire output directory
- // into a srcjar.
- rule.Command().
- BuiltTool(ctx, "soong_zip").
- Flag("-jar").
- FlagWithOutput("-o ", srcJarFile).
- FlagWithArg("-C ", outDir.String()).
- FlagWithArg("-D ", outDir.String())
+ rule.Command().Text("rm -rf").Flag(outDir.String())
+ rule.Command().Text("mkdir -p").Flag(outDir.String())
- rule.Command().Text("rm -rf").Flag(outDir.String())
+ for _, protoFile := range shard {
+ depFile := srcJarFile.InSameDir(ctx, protoFile.String()+".d")
+ rule.Command().Text("mkdir -p").Flag(filepath.Dir(depFile.String()))
+ android.ProtoRule(ctx, rule, protoFile, flags, flags.Deps, outDir, depFile, nil)
+ }
- rule.Build(pctx, ctx, "protoc_"+protoFile.Rel(), "protoc "+protoFile.Rel())
+ // Proto generated java files have an unknown package name in the path, so package the entire output directory
+ // into a srcjar.
+ rule.Command().
+ BuiltTool(ctx, "soong_zip").
+ Flag("-jar").
+ Flag("-write_if_changed").
+ FlagWithOutput("-o ", srcJarFile).
+ FlagWithArg("-C ", outDir.String()).
+ FlagWithArg("-D ", outDir.String())
- return srcJarFile
+ rule.Command().Text("rm -rf").Flag(outDir.String())
+
+ rule.Restat()
+
+ ruleName := "protoc"
+ ruleDesc := "protoc"
+ if len(shards) > 1 {
+ ruleName += "_" + strconv.Itoa(i)
+ ruleDesc += " " + strconv.Itoa(i)
+ }
+
+ rule.Build(pctx, ctx, ruleName, ruleDesc)
+ }
+
+ return srcJarFiles
}
func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) {
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 88e21d7..5001b47 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -250,7 +250,10 @@
}
checkClasspath := func(t *testing.T, ctx *android.TestContext) {
- javac := ctx.ModuleForTests("foo", variant).Rule("javac")
+ foo := ctx.ModuleForTests("foo", variant)
+ javac := foo.Rule("javac")
+
+ aidl := foo.MaybeRule("aidl")
got := javac.Args["bootClasspath"]
if got != bc {
@@ -263,6 +266,9 @@
}
var deps []string
+ if aidl.Rule != nil {
+ deps = append(deps, aidl.Output.String())
+ }
if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
deps = append(deps, bootclasspath...)
}
@@ -290,12 +296,8 @@
if testcase.host != android.Host {
aidl := ctx.ModuleForTests("foo", variant).Rule("aidl")
- aidlFlags := aidl.Args["aidlFlags"]
- // Trim trailing "-I." to avoid having to specify it in every test
- aidlFlags = strings.TrimSpace(strings.TrimSuffix(aidlFlags, "-I."))
-
- if g, w := aidlFlags, testcase.aidl; g != w {
- t.Errorf("want aidl flags %q, got %q", w, g)
+ if g, w := aidl.RuleParams.Command, testcase.aidl+" -I."; !strings.Contains(g, w) {
+ t.Errorf("want aidl command to contain %q, got %q", w, g)
}
}
})
diff --git a/makedeps/deps.go b/makedeps/deps.go
index e64e6f7..db49532 100644
--- a/makedeps/deps.go
+++ b/makedeps/deps.go
@@ -57,10 +57,12 @@
return nil, fmt.Errorf("%sunsupported variable expansion: %v", pos(node), x.Target.Dump())
}
outputs := x.Target.Words()
- if len(outputs) == 0 {
- return nil, fmt.Errorf("%smissing output: %v", pos(node), x)
+ if len(outputs) > 0 {
+ ret.Output = outputs[0].Value(nil)
+ } else {
+ // TODO(b/141372861): put this back
+ //return nil, fmt.Errorf("%smissing output: %v", pos(node), x)
}
- ret.Output = outputs[0].Value(nil)
if !x.Prerequisites.Const() {
return nil, fmt.Errorf("%sunsupported variable expansion: %v", pos(node), x.Prerequisites.Dump())
diff --git a/makedeps/deps_test.go b/makedeps/deps_test.go
index a32df65..ac2f699 100644
--- a/makedeps/deps_test.go
+++ b/makedeps/deps_test.go
@@ -147,6 +147,20 @@
},
},
},
+ {
+ // TODO(b/141372861): remove this
+ // AIDL produces a dep file with no output file for a parcelable (b/
+ name: "AIDL parcelable",
+ input: ` : \
+ frameworks/base/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl
+`,
+ output: Deps{
+ Output: "",
+ Inputs: []string{
+ "frameworks/base/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl",
+ },
+ },
+ },
}
for _, tc := range testCases {
diff --git a/python/androidmk.go b/python/androidmk.go
index 1e51e7b..aae7ced 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -89,12 +89,11 @@
ret.Required = append(ret.Required, "libc++")
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- path := installer.path.RelPathString()
- dir, file := filepath.Split(path)
+ path, file := filepath.Split(installer.path.ToMakePath().String())
stem := strings.TrimSuffix(file, filepath.Ext(file))
fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+filepath.Ext(file))
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(installer.androidMkSharedLibs, " "))
})
diff --git a/python/installer.go b/python/installer.go
index 62f36f4..396f036 100644
--- a/python/installer.go
+++ b/python/installer.go
@@ -33,7 +33,7 @@
dir64 string
relative string
- path android.OutputPath
+ path android.InstallPath
androidMkSharedLibs []string
}
@@ -47,12 +47,12 @@
var _ installer = (*pythonInstaller)(nil)
-func (installer *pythonInstaller) installDir(ctx android.ModuleContext) android.OutputPath {
+func (installer *pythonInstaller) installDir(ctx android.ModuleContext) android.InstallPath {
dir := installer.dir
if ctx.Arch().ArchType.Multilib == "lib64" && installer.dir64 != "" {
dir = installer.dir64
}
- if !ctx.Host() && !ctx.Arch().Native {
+ if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
return android.PathForModuleInstall(ctx, dir, installer.relative)
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 107959f..a6208db 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -116,11 +116,10 @@
ret.OutputFile = android.OptionalPathForPath(compiler.path)
}
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- path := compiler.path.RelPathString()
- dir, file := filepath.Split(path)
+ path, file := filepath.Split(compiler.path.ToMakePath().String())
stem, suffix, _ := android.SplitFileExt(file)
fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
})
}
diff --git a/rust/builder.go b/rust/builder.go
index 6611492..104313f 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -29,8 +29,7 @@
Command: "$rustcCmd " +
"-C linker=${config.RustLinker} " +
"-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
- "-o $out $in ${libFlags} $rustcFlags " +
- "&& $rustcCmd --emit=dep-info -o $out.d $in ${libFlags} $rustcFlags",
+ "--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
diff --git a/rust/compiler.go b/rust/compiler.go
index 6c603df..3f02835 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -20,16 +20,22 @@
"android/soong/android"
"android/soong/rust/config"
+ "github.com/google/blueprint/proptools"
)
+func getEdition(compiler *baseCompiler) string {
+ return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition)
+}
+
+func getDenyWarnings(compiler *baseCompiler) bool {
+ return BoolDefault(compiler.Properties.Deny_warnings, config.DefaultDenyWarnings)
+}
+
func NewBaseCompiler(dir, dir64 string) *baseCompiler {
return &baseCompiler{
- Properties: BaseCompilerProperties{
- Edition: &config.DefaultEdition,
- Deny_warnings: config.DefaultDenyWarnings,
- },
- dir: dir,
- dir64: dir64,
+ Properties: BaseCompilerProperties{},
+ dir: dir,
+ dir64: dir64,
}
}
@@ -94,7 +100,7 @@
dir64 string
subDir string
relative string
- path android.OutputPath
+ path android.InstallPath
}
var _ compiler = (*baseCompiler)(nil)
@@ -113,13 +119,14 @@
func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {
- if Bool(compiler.Properties.Deny_warnings) {
+ if getDenyWarnings(compiler) {
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.RustFlags = append(flags.RustFlags, "--edition="+getEdition(compiler))
flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
+ flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
@@ -172,12 +179,12 @@
return compiler.Properties.Crate_name
}
-func (compiler *baseCompiler) installDir(ctx ModuleContext) android.OutputPath {
+func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath {
dir := compiler.dir
if ctx.toolchain().Is64Bit() && compiler.dir64 != "" {
dir = compiler.dir64
}
- if (!ctx.Host() && !ctx.Arch().Native) || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ if !ctx.Host() || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
return android.PathForModuleInstall(ctx, dir, compiler.subDir,
diff --git a/rust/config/global.go b/rust/config/global.go
index c66c3c1..7846d21 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -17,8 +17,6 @@
import (
"strings"
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
_ "android/soong/cc/config"
)
@@ -35,7 +33,11 @@
"libtest",
}
- DefaultDenyWarnings = proptools.BoolPtr(true)
+ DefaultDenyWarnings = true
+
+ GlobalRustFlags = []string{
+ "--remap-path-prefix $$(pwd)=",
+ }
deviceGlobalRustFlags = []string{}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 6b9eac1..1925e87 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -17,6 +17,8 @@
import (
"bytes"
"fmt"
+ "io/ioutil"
+ "os"
"strings"
"android/soong/ui/metrics"
@@ -51,7 +53,17 @@
var ret map[string]string
if len(makeVars) > 0 {
- var err error
+ tmpDir, err := ioutil.TempDir("", "dumpvars")
+ if err != nil {
+ return nil, err
+ }
+ defer os.RemoveAll(tmpDir)
+
+ // It's not safe to use the same TMPDIR as the build, as that can be removed.
+ config.Environment().Set("TMPDIR", tmpDir)
+
+ SetupLitePath(ctx, config)
+
ret, err = dumpMakeVars(ctx, config, goals, makeVars, false)
if err != nil {
return ret, err
@@ -208,6 +220,7 @@
"DEFAULT_WARNING_BUILD_MODULE_TYPES",
"DEFAULT_ERROR_BUILD_MODULE_TYPES",
+ "BUILD_BROKEN_PREBUILT_ELF_FILES",
"BUILD_BROKEN_USES_BUILD_AUX_EXECUTABLE",
"BUILD_BROKEN_USES_BUILD_AUX_STATIC_LIBRARY",
"BUILD_BROKEN_USES_BUILD_COPY_HEADERS",
diff --git a/ui/build/path.go b/ui/build/path.go
index 0e1c02c..c34ba1b 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -18,6 +18,7 @@
"fmt"
"io/ioutil"
"os"
+ "os/exec"
"path/filepath"
"runtime"
"strings"
@@ -53,6 +54,51 @@
return ret
}
+// A "lite" version of SetupPath used for dumpvars, or other places that need
+// minimal overhead (but at the expense of logging).
+func SetupLitePath(ctx Context, config Config) {
+ if config.pathReplaced {
+ return
+ }
+
+ ctx.BeginTrace(metrics.RunSetupTool, "litepath")
+ defer ctx.EndTrace()
+
+ origPath, _ := config.Environment().Get("PATH")
+ myPath, _ := config.Environment().Get("TMPDIR")
+ myPath = filepath.Join(myPath, "path")
+ ensureEmptyDirectoriesExist(ctx, myPath)
+
+ os.Setenv("PATH", origPath)
+ for name, pathConfig := range paths.Configuration {
+ if !pathConfig.Symlink {
+ continue
+ }
+
+ origExec, err := exec.LookPath(name)
+ if err != nil {
+ continue
+ }
+ origExec, err = filepath.Abs(origExec)
+ if err != nil {
+ continue
+ }
+
+ err = os.Symlink(origExec, filepath.Join(myPath, name))
+ if err != nil {
+ ctx.Fatalln("Failed to create symlink:", err)
+ }
+ }
+
+ myPath, _ = filepath.Abs(myPath)
+
+ prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
+ myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
+
+ config.Environment().Set("PATH", myPath)
+ config.pathReplaced = true
+}
+
func SetupPath(ctx Context, config Config) {
if config.pathReplaced {
return
diff --git a/vnames.json b/vnames.json
index 7b34c52..f9d3adc 100644
--- a/vnames.json
+++ b/vnames.json
@@ -2,7 +2,7 @@
{
"pattern": "out/(.*)",
"vname": {
- "corpus": "CORPUS",
+ "corpus": "android.googlesource.com/platform/superproject",
"root": "out",
"path": "@1@"
}
@@ -10,7 +10,7 @@
{
"pattern": "(.*)",
"vname": {
- "corpus": "CORPUS",
+ "corpus": "android.googlesource.com/platform/superproject",
"path": "@1@"
}
}
diff --git a/xml/xml_test.go b/xml/xml_test.go
index ae3e9fe..f2a440f 100644
--- a/xml/xml_test.go
+++ b/xml/xml_test.go
@@ -15,15 +15,40 @@
package xml
import (
- "android/soong/android"
"io/ioutil"
"os"
"testing"
+
+ "android/soong/android"
)
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_xml_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())
+}
+
func testXml(t *testing.T, bp string) *android.TestContext {
- config, buildDir := setup(t)
- defer teardown(buildDir)
+ config := android.TestArchConfig(buildDir, nil)
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
ctx.RegisterModuleType("prebuilt_etc_xml", android.ModuleFactoryAdaptor(PrebuiltEtcXmlFactory))
@@ -45,21 +70,6 @@
return ctx
}
-func setup(t *testing.T) (config android.Config, buildDir string) {
- buildDir, err := ioutil.TempDir("", "soong_xml_test")
- if err != nil {
- t.Fatal(err)
- }
-
- config = android.TestArchConfig(buildDir, nil)
-
- return
-}
-
-func teardown(buildDir string) {
- os.RemoveAll(buildDir)
-}
-
func assertEqual(t *testing.T, name, expected, actual string) {
t.Helper()
if expected != actual {
@@ -103,5 +113,5 @@
}
m := ctx.ModuleForTests("foo.xml", "android_arm64_armv8-a").Module().(*prebuiltEtcXml)
- assertEqual(t, "installDir", "target/product/test_device/system/etc", m.InstallDirPath().RelPathString())
+ assertEqual(t, "installDir", buildDir+"/target/product/test_device/system/etc", m.InstallDirPath().String())
}