Merge "Workaround unexported sancov symbols. Fix multiple sanitizer RT deps."
diff --git a/android/apex.go b/android/apex.go
index 557febf..d3c0710 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -19,7 +19,6 @@
"sync"
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
// ApexModule is the interface that a module type is expected to implement if
@@ -76,18 +75,11 @@
// CreateApexVariations.
setApexName(apexName string)
- // 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".
@@ -143,23 +135,23 @@
return false
}
-func (m *ApexModuleBase) NoApex() bool {
- 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 {
+func CheckAvailableForApex(what string, apex_available []string) bool {
+ if len(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))
+ return InList(what, apex_available) ||
+ (what != availableToPlatform && InList(availableToAnyApex, apex_available))
+}
+
+func (m *ApexModuleBase) AvailableFor(what string) bool {
+ return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
}
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
@@ -167,7 +159,7 @@
if n == availableToPlatform || n == availableToAnyApex {
continue
}
- if !mctx.OtherModuleExists(n) {
+ if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
}
}
@@ -178,7 +170,7 @@
m.checkApexAvailableProperty(mctx)
sort.Strings(m.apexVariations)
variations := []string{}
- availableForPlatform := m.AvailableFor(availableToPlatform)
+ availableForPlatform := mctx.Module().(ApexModule).AvailableFor(availableToPlatform)
if availableForPlatform {
variations = append(variations, "") // Original variation for platform
}
diff --git a/android/arch.go b/android/arch.go
index b5b52a9..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 {
@@ -1361,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 != "" {
@@ -1513,7 +1507,7 @@
if err != nil {
return nil, err
}
- arch.Native = false
+
ret = append(ret, Target{
Os: Android,
Arch: arch,
@@ -1542,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/config.go b/android/config.go
index d03d38e..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()
@@ -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 1e5ff21..604cb9c 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -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 a1a01a5..5d1a609 100644
--- a/android/module.go
+++ b/android/module.go
@@ -147,16 +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
@@ -196,6 +197,7 @@
InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
+ InstallInRoot() bool
InstallBypassMake() bool
SkipInstall()
ExportedToMake() bool
@@ -512,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()
@@ -595,7 +608,7 @@
nameProperties nameProperties
commonProperties commonProperties
- variableProperties variableProperties
+ variableProperties interface{}
hostAndDeviceProperties hostAndDeviceProperties
generalProperties []interface{}
archProperties [][]interface{}
@@ -846,6 +859,10 @@
return Bool(m.commonProperties.Recovery)
}
+func (m *ModuleBase) InstallInRoot() bool {
+ return false
+}
+
func (m *ModuleBase) InstallBypassMake() bool {
return false
}
@@ -1183,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 {
@@ -1522,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
}
@@ -1551,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)
@@ -1597,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)
@@ -1626,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 510e63c..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"
)
@@ -244,8 +246,23 @@
}
func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
- inherited := []interface{}{&t.Module().base().commonProperties, &t.Module().base().variableProperties}
+ 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
}
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 8bd2c61..8dbb086 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -47,6 +47,7 @@
InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRecovery() bool
+ InstallInRoot() bool
InstallBypassMake() bool
}
@@ -792,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
}
@@ -820,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))
@@ -846,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 {
@@ -1118,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)
@@ -1140,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
@@ -1159,8 +1197,12 @@
} 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() {
@@ -1169,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 b66eb1e..2e67272 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -204,6 +204,7 @@
inTestcases bool
inSanitizerDir bool
inRecovery bool
+ inRoot bool
}
func (moduleInstallPathContextImpl) Fs() pathtools.FileSystem {
@@ -232,6 +233,10 @@
return m.inRecovery
}
+func (m moduleInstallPathContextImpl) InstallInRoot() bool {
+ return m.inRoot
+}
+
func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
return false
}
@@ -313,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 aff8d50..9382c19 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -149,15 +149,6 @@
androidAppTag = dependencyTag{name: "androidApp"}
)
-var (
- whitelistNoApex = map[string][]string{
- "apex_test_build_features": []string{"libbinder"},
- "com.android.media.swcodec": []string{"libbinder"},
- "test_com.android.media.swcodec": []string{"libbinder"},
- "com.android.vndk": []string{"libbinder"},
- }
-)
-
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java")
@@ -191,11 +182,19 @@
android.RegisterModuleType("apex_defaults", defaultsFactory)
android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator).Parallel()
- ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator).Parallel()
- })
+ android.PreDepsMutators(RegisterPreDepsMutators)
android.PostDepsMutators(RegisterPostDepsMutators)
+
+ android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
+ apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
+ sort.Strings(*apexFileContextsInfos)
+ ctx.Strict("APEX_FILE_CONTEXTS_INFOS", strings.Join(*apexFileContextsInfos, " "))
+ })
+}
+
+func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
+ ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -210,42 +209,39 @@
vndkApexListMutex sync.Mutex
)
-func vndkApexList(config android.Config) map[string]*apexBundle {
+func vndkApexList(config android.Config) map[string]string {
return config.Once(vndkApexListKey, func() interface{} {
- return map[string]*apexBundle{}
- }).(map[string]*apexBundle)
+ return map[string]string{}
+ }).(map[string]string)
}
-// apexVndkGatherMutator gathers "apex_vndk" modules and puts them in a map with vndk_version as a key.
-func apexVndkGatherMutator(mctx android.TopDownMutatorContext) {
+func apexVndkMutator(mctx android.TopDownMutatorContext) {
if ab, ok := mctx.Module().(*apexBundle); ok && ab.vndkApex {
if ab.IsNativeBridgeSupported() {
mctx.PropertyErrorf("native_bridge_supported", "%q doesn't support native bridge binary.", mctx.ModuleType())
}
- vndkVersion := proptools.StringDefault(ab.vndkProperties.Vndk_version, mctx.DeviceConfig().PlatformVndkVersion())
+
+ vndkVersion := ab.vndkVersion(mctx.DeviceConfig())
+ // Ensure VNDK APEX mount point is formatted as com.android.vndk.v###
+ ab.properties.Apex_name = proptools.StringPtr("com.android.vndk.v" + vndkVersion)
+
+ // vndk_version should be unique
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)
}
- vndkApexList[vndkVersion] = ab
+ vndkApexList[vndkVersion] = mctx.ModuleName()
}
}
-// apexVndkAddDepsMutator adds (reverse) dependencies from vndk libs to apex_vndk modules.
-// It filters only libs with matching targets.
-func apexVndkAddDepsMutator(mctx android.BottomUpMutatorContext) {
- if cc, ok := mctx.Module().(*cc.Module); ok && cc.IsVndkOnSystem() {
+func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(*cc.Module); ok && cc.IsForVndkApex(mctx, m) {
+ vndkVersion := m.VndkVersion()
vndkApexList := vndkApexList(mctx.Config())
- if ab, ok := vndkApexList[cc.VndkVersion()]; ok {
- targetArch := cc.Target().String()
- for _, target := range ab.MultiTargets() {
- if target.String() == targetArch {
- mctx.AddReverseDependency(mctx.Module(), sharedLibTag, ab.Name())
- break
- }
- }
+ if vndkApex, ok := vndkApexList[vndkVersion]; ok {
+ mctx.AddReverseDependency(mctx.Module(), sharedLibTag, vndkApex)
}
}
}
@@ -280,14 +276,40 @@
func apexMutator(mctx android.BottomUpMutatorContext) {
if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
am.CreateApexVariations(mctx)
- } else if _, ok := mctx.Module().(*apexBundle); ok {
+ } else if a, ok := mctx.Module().(*apexBundle); ok {
// apex bundle itself is mutated so that it and its modules have same
// apex variant.
apexBundleName := mctx.ModuleName()
mctx.CreateVariations(apexBundleName)
+
+ // collects APEX list
+ if mctx.Device() && a.installable() {
+ addApexFileContextsInfos(mctx, a)
+ }
}
}
+var (
+ apexFileContextsInfosKey = android.NewOnceKey("apexFileContextsInfosKey")
+ apexFileContextsInfosMutex sync.Mutex
+)
+
+func apexFileContextsInfos(config android.Config) *[]string {
+ return config.Once(apexFileContextsInfosKey, func() interface{} {
+ return &[]string{}
+ }).(*[]string)
+}
+
+func addApexFileContextsInfos(ctx android.BaseModuleContext, a *apexBundle) {
+ apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
+ fileContextsName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
+
+ apexFileContextsInfosMutex.Lock()
+ defer apexFileContextsInfosMutex.Unlock()
+ apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
+ *apexFileContextsInfos = append(*apexFileContextsInfos, apexName+":"+fileContextsName)
+}
+
func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
if ab, ok := mctx.Module().(*apexBundle); ok {
if !mctx.Config().FlattenApex() || mctx.Config().UnbundledBuild() {
@@ -533,7 +555,14 @@
case nativeTest:
return "NATIVE_TESTS"
case app:
- return "APPS"
+ // b/142537672 Why isn't this APP? We want to have full control over
+ // the paths and file names of the apk file under the flattend APEX.
+ // If this is set to APP, then the paths and file names are modified
+ // by the Make build system. For example, it is installed to
+ // /system/apex/<apexname>/app/<Appname>/<apexname>.<Appname>/ instead of
+ // /system/apex/<apexname>/app/<Appname> because the build system automatically
+ // appends module name (which is <apexname>.<Appname> to the path.
+ return "ETC"
default:
panic(fmt.Errorf("unknown class %d", class))
}
@@ -561,8 +590,8 @@
bundleModuleFile android.WritablePath
outputFiles map[apexPackaging]android.WritablePath
- flattenedOutput android.OutputPath
- installDir android.OutputPath
+ flattenedOutput android.InstallPath
+ installDir android.InstallPath
prebuiltFileToDelete string
@@ -625,7 +654,6 @@
}
func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
-
targets := ctx.MultiTargets()
config := ctx.DeviceConfig()
@@ -796,6 +824,9 @@
}
func (a *apexBundle) getImageVariation(config android.DeviceConfig) string {
+ if a.vndkApex {
+ return "vendor." + a.vndkVersion(config)
+ }
if config.VndkVersion() != "" && proptools.Bool(a.properties.Use_vendor) {
return "vendor." + config.PlatformVndkVersion()
} else {
@@ -867,9 +898,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) {
@@ -892,9 +921,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()
@@ -1035,7 +1062,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})
@@ -1170,10 +1197,6 @@
}
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
- } else if depTag == android.DefaultsDepTag {
- return false
- } else if am.NoApex() && !android.InList(depName, whitelistNoApex[ctx.ModuleName()]) {
- ctx.ModuleErrorf("tries to include no_apex module %s", depName)
}
}
}
@@ -1205,22 +1228,14 @@
return filesInfo[i].builtFile.String() < filesInfo[j].builtFile.String()
})
- // check no_apex modules
- whitelist := whitelistNoApex[ctx.ModuleName()]
- for i := range filesInfo {
- if am, ok := filesInfo[i].module.(android.ApexModule); ok {
- if am.NoApex() && !android.InList(filesInfo[i].moduleName, whitelist) {
- ctx.ModuleErrorf("tries to include no_apex module %s", filesInfo[i].moduleName)
- }
- }
- }
-
// 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
+ if !ctx.Host() {
+ 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
+ }
}
}
}
@@ -1228,7 +1243,7 @@
// 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 {
- filesInfo[i].moduleName = ctx.ModuleName() + "." + filesInfo[i].moduleName
+ filesInfo[i].moduleName = filesInfo[i].moduleName + "." + ctx.ModuleName()
}
a.installDir = android.PathForModuleInstall(ctx, "apex")
@@ -1265,7 +1280,8 @@
// instead of `android.PathForOutput`) to return the correct path to the flattened
// APEX (as its contents is installed by Make, not Soong).
factx := flattenedApexContext{ctx}
- a.flattenedOutput = android.PathForModuleInstall(&factx, "apex", factx.ModuleName())
+ apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
+ a.flattenedOutput = android.PathForModuleInstall(&factx, "apex", apexName)
if a.apexTypes.zip() {
a.buildUnflattenedApex(ctx, zipApex)
@@ -1553,7 +1569,7 @@
if a.installable() {
// For flattened APEX, do nothing but make sure that apex_manifest.json and apex_pubkey are also copied along
// with other ordinary files.
- a.filesInfo = append(a.filesInfo, apexFile{a.manifestOut, ctx.ModuleName() + ".apex_manifest.json", ".", etc, nil, nil})
+ a.filesInfo = append(a.filesInfo, apexFile{a.manifestOut, "apex_manifest.json." + ctx.ModuleName(), ".", etc, nil, nil})
// rename to apex_pubkey
copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
@@ -1562,11 +1578,12 @@
Input: a.public_key_file,
Output: copiedPubkey,
})
- a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, ctx.ModuleName() + ".apex_pubkey", ".", etc, nil, nil})
+ a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, "apex_pubkey." + ctx.ModuleName(), ".", etc, nil, nil})
if ctx.Config().FlattenApex() {
+ apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
for _, fi := range a.filesInfo {
- dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
+ dir := filepath.Join("apex", apexName, fi.installDir)
target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
for _, sym := range fi.symlinks {
ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target)
@@ -1597,7 +1614,7 @@
}}
}
-func (a *apexBundle) androidMkForFiles(w io.Writer, name, moduleDir string, apexType apexPackaging) []string {
+func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string, apexType apexPackaging) []string {
moduleNames := []string{}
for _, fi := range a.filesInfo {
@@ -1621,12 +1638,11 @@
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName+suffix)
// /apex/<apex_name>/{lib|framework|...}
- pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex",
- proptools.StringDefault(a.properties.Apex_name, name), fi.installDir)
+ pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, 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(),
+ apexName, fi.installDir))
if !a.isFlattenedVariant() {
fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
}
@@ -1706,7 +1722,8 @@
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
moduleNames := []string{}
if a.installable() {
- moduleNames = a.androidMkForFiles(w, name, moduleDir, apexType)
+ apexName := proptools.StringDefault(a.properties.Apex_name, name)
+ moduleNames = a.androidMkForFiles(w, apexName, moduleDir, apexType)
}
if a.isFlattenedVariant() {
@@ -1735,7 +1752,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 {
@@ -1746,7 +1763,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)")
@@ -1805,6 +1822,14 @@
return bundle
}
+func (a *apexBundle) vndkVersion(config android.DeviceConfig) string {
+ vndkVersion := proptools.StringDefault(a.vndkProperties.Vndk_version, "current")
+ if vndkVersion == "current" {
+ vndkVersion = config.PlatformVndkVersion()
+ }
+ return vndkVersion
+}
+
//
// Defaults
//
@@ -1840,7 +1865,7 @@
properties PrebuiltProperties
inputApex android.Path
- installDir android.OutputPath
+ installDir android.InstallPath
installFilename string
outputApex android.WritablePath
}
@@ -1987,7 +2012,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 ecfa46f..a420c14 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -18,6 +18,7 @@
"io/ioutil"
"os"
"reflect"
+ "sort"
"strings"
"testing"
@@ -85,6 +86,10 @@
}
}
+func withBinder32bit(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
+}
+
func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
config := android.TestArchConfig(buildDir, nil)
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
@@ -102,9 +107,6 @@
ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory))
- ctx.RegisterModuleType("cc_defaults", android.ModuleFactoryAdaptor(func() android.Module {
- return cc.DefaultsFactory()
- }))
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
@@ -135,13 +137,10 @@
ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
ctx.BottomUp("version", cc.VersionMutator).Parallel()
ctx.BottomUp("begin", cc.BeginMutator).Parallel()
- ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator)
- ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator)
})
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_deps", apexDepsMutator)
- ctx.BottomUp("apex", apexMutator)
- ctx.BottomUp("apex_uses", apexUsesMutator)
ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
})
@@ -1210,16 +1209,22 @@
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
// APEX variant has __ANDROID_APEX__=<apexname> defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
// APEX variant has __ANDROID_APEX__=<apexname> defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_otherapex").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
}
func TestHeaderLibsDependency(t *testing.T) {
@@ -1270,6 +1275,74 @@
ensureContains(t, cFlags, "-Imy_include")
}
+func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
+ t.Helper()
+ apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName).Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ imageApexDir := "/image.apex/"
+ dstFiles := []string{}
+ for _, cmd := range strings.Split(copyCmds, "&&") {
+ cmd = strings.TrimSpace(cmd)
+ if cmd == "" {
+ continue
+ }
+ terms := strings.Split(cmd, " ")
+ switch terms[0] {
+ case "mkdir":
+ case "cp":
+ if len(terms) != 3 {
+ t.Fatal("copyCmds contains invalid cp command", cmd)
+ }
+ dst := terms[2]
+ index := strings.Index(dst, imageApexDir)
+ if index == -1 {
+ t.Fatal("copyCmds should copy a file to image.apex/", cmd)
+ }
+ dstFile := dst[index+len(imageApexDir):]
+ dstFiles = append(dstFiles, dstFile)
+ default:
+ t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
+ }
+ }
+ sort.Strings(dstFiles)
+ sort.Strings(files)
+ missing := []string{}
+ surplus := []string{}
+ i := 0
+ j := 0
+ for i < len(dstFiles) && j < len(files) {
+ if dstFiles[i] == files[j] {
+ i++
+ j++
+ } else if dstFiles[i] < files[j] {
+ surplus = append(surplus, dstFiles[i])
+ i++
+ } else {
+ missing = append(missing, files[j])
+ j++
+ }
+ }
+ if i < len(dstFiles) {
+ surplus = append(surplus, dstFiles[i:]...)
+ }
+ if j < len(files) {
+ missing = append(missing, files[j:]...)
+ }
+
+ failed := false
+ if len(surplus) > 0 {
+ t.Log("surplus files", surplus)
+ failed = true
+ }
+ if len(missing) > 0 {
+ t.Log("missing files", missing)
+ failed = true
+ }
+ if failed {
+ t.Fail()
+ }
+}
+
func TestVndkApexCurrent(t *testing.T) {
ctx, _ := testApex(t, `
apex_vndk {
@@ -1308,12 +1381,12 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
- ensureContains(t, copyCmds, "image.apex/lib/libvndksp.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndksp.so")
+ ensureExactContents(t, ctx, "myapex", []string{
+ "lib/libvndk.so",
+ "lib/libvndksp.so",
+ "lib64/libvndk.so",
+ "lib64/libvndksp.so",
+ })
}
func TestVndkApexWithPrebuilt(t *testing.T) {
@@ -1331,8 +1404,8 @@
}
cc_prebuilt_library_shared {
- name: "libvndkshared",
- srcs: ["libvndkshared.so"],
+ name: "libvndk",
+ srcs: ["libvndk.so"],
vendor_available: true,
vndk: {
enabled: true,
@@ -1340,13 +1413,33 @@
system_shared_libs: [],
stl: "none",
}
+
+ cc_prebuilt_library_shared {
+ name: "libvndk.arm",
+ srcs: ["libvndk.arm.so"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ enabled: false,
+ arch: {
+ arm: {
+ enabled: true,
+ },
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
`, withFiles(map[string][]byte{
- "libvndkshared.so": nil,
+ "libvndk.so": nil,
+ "libvndk.arm.so": nil,
}))
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndkshared.so")
+ ensureExactContents(t, ctx, "myapex", []string{
+ "lib/libvndk.so",
+ "lib/libvndk.arm.so",
+ "lib64/libvndk.so",
+ })
}
func TestVndkApexVersion(t *testing.T) {
@@ -1364,15 +1457,22 @@
private_key: "testkey.pem",
}
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
+ vndk_prebuilt_shared {
+ name: "libvndk27",
+ version: "27",
vendor_available: true,
vndk: {
enabled: true,
},
- system_shared_libs: [],
- stl: "none",
+ target_arch: "arm64",
+ arch: {
+ arm: {
+ srcs: ["libvndk27_arm.so"],
+ },
+ arm64: {
+ srcs: ["libvndk27_arm64.so"],
+ },
+ },
}
vndk_prebuilt_shared {
@@ -1382,17 +1482,27 @@
vndk: {
enabled: true,
},
- srcs: ["libvndk27.so"],
- }
+ target_arch: "x86_64",
+ arch: {
+ x86: {
+ srcs: ["libvndk27_x86.so"],
+ },
+ x86_64: {
+ srcs: ["libvndk27_x86_64.so"],
+ },
+ },
+ }
`, withFiles(map[string][]byte{
- "libvndk27.so": nil,
+ "libvndk27_arm.so": nil,
+ "libvndk27_arm64.so": nil,
+ "libvndk27_x86.so": nil,
+ "libvndk27_x86_64.so": nil,
}))
- apexRule := ctx.ModuleForTests("myapex_v27", "android_common_myapex_v27").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndk27.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndk27.so")
- ensureNotContains(t, copyCmds, "image.apex/lib/libvndk.so")
+ ensureExactContents(t, ctx, "myapex_v27", []string{
+ "lib/libvndk27_arm.so",
+ "lib64/libvndk27_arm64.so",
+ })
}
func TestVndkApexErrorWithDuplicateVersion(t *testing.T) {
@@ -1441,6 +1551,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,21 +1610,17 @@
}
`, 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"},
},
}))
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
-
- // apex
- ensureNotContains(t, copyCmds, "image.apex/lib/x86/libvndk.so")
- ensureNotContains(t, copyCmds, "image.apex/lib64/x86_64/libvndk.so")
+ ensureExactContents(t, ctx, "myapex", []string{
+ "lib/libvndk.so",
+ "lib64/libvndk.so",
+ })
}
func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
@@ -1516,6 +1653,70 @@
`)
}
+func TestVndkApexWithBinder32(t *testing.T) {
+ ctx, _ := testApex(t,
+ `
+ apex_vndk {
+ name: "myapex_v27",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ vndk_version: "27",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ vndk_prebuilt_shared {
+ name: "libvndk27",
+ version: "27",
+ target_arch: "arm",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm: {
+ srcs: ["libvndk27.so"],
+ }
+ },
+ }
+
+ vndk_prebuilt_shared {
+ name: "libvndk27",
+ version: "27",
+ target_arch: "arm",
+ binder32bit: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm: {
+ srcs: ["libvndk27binder32.so"],
+ }
+ },
+ }
+ `,
+ withFiles(map[string][]byte{
+ "libvndk27.so": nil,
+ "libvndk27binder32.so": nil,
+ }),
+ withBinder32bit,
+ withTargets(map[android.OsType][]android.Target{
+ android.Android: []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ },
+ }),
+ )
+
+ ensureExactContents(t, ctx, "myapex_v27", []string{
+ "lib/libvndk27binder32.so",
+ })
+}
+
func TestDependenciesInApexManifest(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -1864,8 +2065,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)
}
@@ -2026,12 +2227,12 @@
var builder strings.Builder
data.Custom(&builder, name, prefix, "", data)
androidMk := builder.String()
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest1\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest2\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest3\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_manifest.json\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_pubkey\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest1.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest2.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest3.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.json.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := apex_pubkey.myapex\n")
ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n")
}
@@ -2151,200 +2352,6 @@
`)
}
-func TestApexUsesFailsIfUseNoApex(t *testing.T) {
- // 'no_apex' prevents a module to be included in an apex
- testApexError(t, `tries to include no_apex module mylib2`, `
- apex {
- name: "commonapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- shared_libs: ["mylib2"],
- system_shared_libs: [],
- stl: "none",
- }
-
- cc_library {
- name: "mylib2",
- srcs: ["mylib.cpp"],
- system_shared_libs: [],
- stl: "none",
- no_apex: true,
- }
- `)
-
- // respect 'no_apex' even with static link
- testApexError(t, `tries to include no_apex module mylib2`, `
- apex {
- name: "commonapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- static_libs: ["mylib2"],
- system_shared_libs: [],
- stl: "none",
- }
-
- cc_library {
- name: "mylib2",
- srcs: ["mylib.cpp"],
- system_shared_libs: [],
- stl: "none",
- no_apex: true,
- }
- `)
-
- // 'no_apex' can be applied via defaults
- testApexError(t, `tries to include no_apex module mylib2`, `
- apex {
- name: "commonapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- static_libs: ["mylib2"],
- system_shared_libs: [],
- stl: "none",
- }
-
- cc_defaults {
- name: "mylib2_defaults",
- system_shared_libs: [],
- stl: "none",
- no_apex: true,
- }
-
- cc_library {
- name: "mylib2",
- srcs: ["mylib.cpp"],
- defaults: ["mylib2_defaults"],
- }
- `)
-}
-
-func TestNoApexWorksWithWhitelist(t *testing.T) {
-
- testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- shared_libs: ["mylib2"],
- system_shared_libs: [],
- stl: "none",
- }
-
- cc_defaults {
- name: "mylib2_defaults",
- system_shared_libs: [],
- stl: "none",
- no_apex: true,
- }
-
- cc_library {
- name: "mylib2",
- srcs: ["mylib.cpp"],
- defaults: ["mylib2_defaults"],
- }
- `, func(fs map[string][]byte, config android.Config) {
- whitelistNoApex = map[string][]string{
- "myapex": []string{"mylib2"},
- }
- })
-}
-
-func TestNoApexCanBeDependedOnViaStubs(t *testing.T) {
- ctx, _ := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- shared_libs: ["mylib2"],
- system_shared_libs: [],
- stl: "none",
- }
-
- cc_library {
- name: "mylib2",
- srcs: ["mylib.cpp"],
- shared_libs: ["mylib3"],
- system_shared_libs: [],
- stl: "none",
- stubs: {
- versions: ["1", "2", "3"],
- },
- }
-
- // this won't be included in "myapex", so 'no_apex' is still valid in this case.
- cc_library {
- name: "mylib3",
- srcs: ["mylib.cpp"],
- system_shared_libs: [],
- stl: "none",
- no_apex: true,
- }
- `)
-
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
- apexRule := module.Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
-
- ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
- ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
- ensureNotContains(t, copyCmds, "image.apex/lib64/mylib3.so")
-}
-
func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
testApexError(t, `module "myapex" .* depends on disabled module "libfoo"`, `
apex {
@@ -2572,6 +2579,36 @@
// 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")
+
+ ctx, _ = testApex(t, `
+ 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: ["myapex"],
+ static: {
+ apex_available: ["//apex_available:platform"],
+ },
+ }`)
+
+ // shared variant of libfoo is only available to myapex
+ ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
+ // but the static variant is available to both myapex and the platform
+ ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_static_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_static")
}
func TestMain(m *testing.M) {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index aab4edd..f6b26d2 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -93,6 +93,11 @@
fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
if c.isVndk() && !c.static() {
fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.vndkVersion())
+ // VNDK libraries available to vendor are not installed because
+ // they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go)
+ if !c.isVndkExt() {
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ }
}
}
},
@@ -350,11 +355,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 +399,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 0f2cb4c..f6f8abb 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -488,15 +488,6 @@
return ""
}
-// IsVndkOnSystem returns true if a module is supposed to be a vndk library provided by system to vendor
-func (c *Module) IsVndkOnSystem() bool {
- if linker, ok := c.linker.(libraryInterface); ok {
- return linker.shared() && c.isVndk() && c.useVndk() && !c.isVndkExt()
- }
-
- return false
-}
-
func (c *Module) VndkVersion() string {
return c.vndkVersion()
}
@@ -552,8 +543,10 @@
}
})
android.InitAndroidArchModule(c, c.hod, c.multilib)
- android.InitApexModule(c)
+
android.InitDefaultableModule(c)
+
+ android.InitApexModule(c)
android.InitSdkAwareModule(c)
return c
@@ -2150,6 +2143,16 @@
return false
}
+func (c *Module) AvailableFor(what string) bool {
+ if linker, ok := c.linker.(interface {
+ availableFor(string) bool
+ }); ok {
+ return c.ApexModuleBase.AvailableFor(what) || linker.availableFor(what)
+ } else {
+ return c.ApexModuleBase.AvailableFor(what)
+ }
+}
+
func (c *Module) installable() bool {
return c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid()
}
@@ -2229,8 +2232,8 @@
&android.ProtoProperties{},
)
- android.InitApexModule(module)
android.InitDefaultsModule(module)
+ android.InitApexModule(module)
return module
}
diff --git a/cc/compiler.go b/cc/compiler.go
index 85ff400..438dee7 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -309,7 +309,6 @@
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
"-isystem "+getCurrentIncludePath(ctx).String(),
"-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
- flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_NDK__")
}
if ctx.useVndk() {
@@ -321,7 +320,9 @@
}
if ctx.apexName() != "" {
+ // TODO(b/142582178): remove the value for __ANDROID_APEX__
flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX__="+ctx.apexName())
+ flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexName())+"__")
}
instructionSet := String(compiler.Properties.Instruction_set)
@@ -529,6 +530,12 @@
return false
}
+// makeDefineString transforms a name of an APEX module into a value to be used as value for C define
+// For example, com.android.foo => COM_ANDROID_FOO
+func makeDefineString(name string) string {
+ return strings.ReplaceAll(strings.ToUpper(name), ".", "_")
+}
+
var gnuToCReplacer = strings.NewReplacer("gnu", "c")
func ndkPathDeps(ctx ModuleContext) android.Paths {
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 0f500b6..43e8c85 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -73,6 +73,7 @@
"-m32",
"-Wl,--large-address-aware",
"-L${WindowsGccRoot}/${WindowsGccTriple}/lib32",
+ "-static-libgcc",
}
windowsX86ClangLdflags = append(ClangFilterUnknownCflags(windowsX86Ldflags), []string{
"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
@@ -86,6 +87,7 @@
"-m64",
"-L${WindowsGccRoot}/${WindowsGccTriple}/lib64",
"-Wl,--high-entropy-va",
+ "-static-libgcc",
}
windowsX8664ClangLdflags = append(ClangFilterUnknownCflags(windowsX8664Ldflags), []string{
"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
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 a41ddc2..80dc76c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -131,6 +131,8 @@
Export_shared_lib_headers []string `android:"arch_variant"`
Export_static_lib_headers []string `android:"arch_variant"`
+
+ Apex_available []string `android:"arch_variant"`
}
type LibraryMutatedProperties struct {
@@ -573,6 +575,8 @@
// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
+
+ availableFor(string) bool
}
func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
@@ -791,9 +795,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)
@@ -1050,7 +1052,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)
@@ -1136,6 +1138,19 @@
return library.MutatedProperties.StubsVersion
}
+func (library *libraryDecorator) availableFor(what string) bool {
+ var list []string
+ if library.static() {
+ list = library.StaticProperties.Static.Apex_available
+ } else if library.shared() {
+ list = library.SharedProperties.Shared.Apex_available
+ }
+ if len(list) == 0 {
+ return false
+ }
+ return android.CheckAvailableForApex(what, list)
+}
+
var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
func versioningMacroNamesList(config android.Config) *map[string]string {
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/vndk.go b/cc/vndk.go
index 14bbf11..2c1856e 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -307,6 +307,31 @@
}
}
+func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool {
+ if !m.Enabled() {
+ return false
+ }
+
+ if m.Target().NativeBridge == android.NativeBridgeEnabled {
+ return false
+ }
+
+ // prebuilt vndk modules should match with device
+ // TODO(b/142675459): Use enabled: to select target device in vndk_prebuilt_shared
+ // When b/142675459 is landed, remove following check
+ if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok && !p.matchesWithDevice(mctx.DeviceConfig()) {
+ return false
+ }
+
+ if lib, ok := m.linker.(libraryInterface); ok {
+ useCoreVariant := m.vndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
+ mctx.DeviceConfig().VndkUseCoreVariant() &&
+ !inList(m.BaseModuleName(), config.VndkMustUseVendorVariantList)
+ return lib.shared() && m.useVndk() && m.isVndk() && !m.isVndkExt() && !useCoreVariant
+ }
+ return false
+}
+
// gather list of vndk-core, vndk-sp, and ll-ndk libs
func VndkMutator(mctx android.BottomUpMutatorContext) {
m, ok := mctx.Module().(*Module)
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 8126e4a..8ed0afb 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -129,6 +129,12 @@
func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
+
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ 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,9 +142,25 @@
// current VNDK prebuilts are only shared libs.
return p.singleSourcePath(ctx)
}
+
+ ctx.Module().SkipInstall()
return nil
}
+func (p *vndkPrebuiltLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+ arches := config.Arches()
+ if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
+ return false
+ }
+ if config.BinderBitness() != p.binderBit() {
+ return false
+ }
+ if len(p.properties.Srcs) == 0 {
+ return false
+ }
+ return true
+}
+
func (p *vndkPrebuiltLibraryDecorator) nativeCoverage() bool {
return false
}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index c378f09..511b840 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")
@@ -581,7 +581,8 @@
}
for _, f := range global.PatternsOnSystemOther {
- if makefileMatch(filepath.Join(SystemPartition, f), dexLocation) {
+ // See comment of SYSTEM_OTHER_ODEX_FILTER for details on the matching.
+ if makefileMatch("/"+f, dexLocation) || makefileMatch(filepath.Join(SystemPartition, f), dexLocation) {
return true
}
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 78f2f3f..bf692fe 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -117,18 +117,17 @@
{
patterns: []string{"app/%"},
moduleTests: []moduleTest{
- {module: systemModule, expectedPartition: "system_other"},
+ {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"},
- {module: systemProductModule, expectedPartition: "system_other/product"},
- {module: productModule, expectedPartition: "product"},
+ {module: systemModule, expectedPartition: "system_other/system"},
+ {module: systemProductModule, expectedPartition: "system_other/system/product"},
+ {module: productModule, expectedPartition: "system_other/product"},
},
},
}
@@ -148,7 +147,7 @@
}
if rule.Installs().String() != wantInstalls.String() {
- t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
+ t.Errorf("\npatterns: %v\nwant installs:\n %v\ngot:\n %v", test.patterns, wantInstalls, rule.Installs())
}
}
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index b8b0e01..c21df4c 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -17,6 +17,7 @@
import (
"fmt"
"io"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -37,11 +38,21 @@
var (
pctx = android.NewPackageContext("android/soong/genrule")
+
+ gensrcsMerge = pctx.AndroidStaticRule("gensrcsMerge", blueprint.RuleParams{
+ Command: "${soongZip} -o ${tmpZip} @${tmpZip}.rsp && ${zipSync} -d ${genDir} ${tmpZip}",
+ CommandDeps: []string{"${soongZip}", "${zipSync}"},
+ Rspfile: "${tmpZip}.rsp",
+ RspfileContent: "${zipArgs}",
+ }, "tmpZip", "genDir", "zipArgs")
)
func init() {
pctx.Import("android/soong/android")
pctx.HostBinToolVariable("sboxCmd", "sbox")
+
+ pctx.HostBinToolVariable("soongZip", "soong_zip")
+ pctx.HostBinToolVariable("zipSync", "zipsync")
}
type SourceFileGenerator interface {
@@ -112,9 +123,9 @@
taskGenerator taskFunc
- deps android.Paths
- rule blueprint.Rule
- rawCommand string
+ deps android.Paths
+ rule blueprint.Rule
+ rawCommands []string
exportedIncludeDirs android.Paths
@@ -122,15 +133,20 @@
outputDeps android.Paths
subName string
+ subDir string
}
-type taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) generateTask
+type taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask
type generateTask struct {
in android.Paths
out android.WritablePaths
+ copyTo android.WritablePaths
+ genDir android.WritablePath
sandboxOuts []string
cmd string
+ shard int
+ shards int
}
func (g *Module) GeneratedSourceFiles() android.Paths {
@@ -169,10 +185,10 @@
if len(g.properties.Export_include_dirs) > 0 {
for _, dir := range g.properties.Export_include_dirs {
g.exportedIncludeDirs = append(g.exportedIncludeDirs,
- android.PathForModuleGen(ctx, ctx.ModuleDir(), dir))
+ android.PathForModuleGen(ctx, g.subDir, ctx.ModuleDir(), dir))
}
} else {
- g.exportedIncludeDirs = append(g.exportedIncludeDirs, android.PathForModuleGen(ctx, ""))
+ g.exportedIncludeDirs = append(g.exportedIncludeDirs, android.PathForModuleGen(ctx, g.subDir))
}
locationLabels := map[string][]string{}
@@ -277,120 +293,170 @@
}
}
- task := g.taskGenerator(ctx, String(g.properties.Cmd), srcFiles)
+ var copyFrom android.Paths
+ var outputFiles android.WritablePaths
+ var zipArgs strings.Builder
- for _, out := range task.out {
- addLocationLabel(out.Rel(), []string{filepath.Join("__SBOX_OUT_DIR__", out.Rel())})
- }
-
- referencedDepfile := false
-
- rawCommand, err := android.ExpandNinjaEscaped(task.cmd, func(name string) (string, bool, error) {
- // report the error directly without returning an error to android.Expand to catch multiple errors in a
- // single run
- reportError := func(fmt string, args ...interface{}) (string, bool, error) {
- ctx.PropertyErrorf("cmd", fmt, args...)
- return "SOONG_ERROR", false, nil
+ for _, task := range g.taskGenerator(ctx, String(g.properties.Cmd), srcFiles) {
+ for _, out := range task.out {
+ addLocationLabel(out.Rel(), []string{filepath.Join("__SBOX_OUT_DIR__", out.Rel())})
}
- switch name {
- case "location":
- if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 {
- return reportError("at least one `tools` or `tool_files` is required if $(location) is used")
+ referencedDepfile := false
+
+ rawCommand, err := android.ExpandNinjaEscaped(task.cmd, func(name string) (string, bool, error) {
+ // report the error directly without returning an error to android.Expand to catch multiple errors in a
+ // single run
+ reportError := func(fmt string, args ...interface{}) (string, bool, error) {
+ ctx.PropertyErrorf("cmd", fmt, args...)
+ return "SOONG_ERROR", false, nil
}
- paths := locationLabels[firstLabel]
- if len(paths) == 0 {
- return reportError("default label %q has no files", firstLabel)
- } else if len(paths) > 1 {
- return reportError("default label %q has multiple files, use $(locations %s) to reference it",
- firstLabel, firstLabel)
- }
- return locationLabels[firstLabel][0], false, nil
- case "in":
- return "${in}", true, nil
- case "out":
- return "__SBOX_OUT_FILES__", false, nil
- case "depfile":
- referencedDepfile = true
- if !Bool(g.properties.Depfile) {
- return reportError("$(depfile) used without depfile property")
- }
- return "__SBOX_DEPFILE__", false, nil
- case "genDir":
- return "__SBOX_OUT_DIR__", false, nil
- default:
- if strings.HasPrefix(name, "location ") {
- label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
- if paths, ok := locationLabels[label]; ok {
- if len(paths) == 0 {
- return reportError("label %q has no files", label)
- } else if len(paths) > 1 {
- return reportError("label %q has multiple files, use $(locations %s) to reference it",
- label, label)
- }
- return paths[0], false, nil
- } else {
- return reportError("unknown location label %q", label)
+
+ switch name {
+ case "location":
+ if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 {
+ return reportError("at least one `tools` or `tool_files` is required if $(location) is used")
}
- } else if strings.HasPrefix(name, "locations ") {
- label := strings.TrimSpace(strings.TrimPrefix(name, "locations "))
- if paths, ok := locationLabels[label]; ok {
- if len(paths) == 0 {
- return reportError("label %q has no files", label)
- }
- return strings.Join(paths, " "), false, nil
- } else {
- return reportError("unknown locations label %q", label)
+ paths := locationLabels[firstLabel]
+ if len(paths) == 0 {
+ return reportError("default label %q has no files", firstLabel)
+ } else if len(paths) > 1 {
+ return reportError("default label %q has multiple files, use $(locations %s) to reference it",
+ firstLabel, firstLabel)
}
- } else {
- return reportError("unknown variable '$(%s)'", name)
+ return locationLabels[firstLabel][0], false, nil
+ case "in":
+ return "${in}", true, nil
+ case "out":
+ return "__SBOX_OUT_FILES__", false, nil
+ case "depfile":
+ referencedDepfile = true
+ if !Bool(g.properties.Depfile) {
+ return reportError("$(depfile) used without depfile property")
+ }
+ return "__SBOX_DEPFILE__", false, nil
+ case "genDir":
+ return "__SBOX_OUT_DIR__", false, nil
+ default:
+ if strings.HasPrefix(name, "location ") {
+ label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
+ if paths, ok := locationLabels[label]; ok {
+ if len(paths) == 0 {
+ return reportError("label %q has no files", label)
+ } else if len(paths) > 1 {
+ return reportError("label %q has multiple files, use $(locations %s) to reference it",
+ label, label)
+ }
+ return paths[0], false, nil
+ } else {
+ return reportError("unknown location label %q", label)
+ }
+ } else if strings.HasPrefix(name, "locations ") {
+ label := strings.TrimSpace(strings.TrimPrefix(name, "locations "))
+ if paths, ok := locationLabels[label]; ok {
+ if len(paths) == 0 {
+ return reportError("label %q has no files", label)
+ }
+ return strings.Join(paths, " "), false, nil
+ } else {
+ return reportError("unknown locations label %q", label)
+ }
+ } else {
+ return reportError("unknown variable '$(%s)'", name)
+ }
}
+ })
+
+ if err != nil {
+ ctx.PropertyErrorf("cmd", "%s", err.Error())
+ return
}
- })
- if err != nil {
- ctx.PropertyErrorf("cmd", "%s", err.Error())
- return
+ if Bool(g.properties.Depfile) && !referencedDepfile {
+ ctx.PropertyErrorf("cmd", "specified depfile=true but did not include a reference to '${depfile}' in cmd")
+ return
+ }
+
+ // tell the sbox command which directory to use as its sandbox root
+ buildDir := android.PathForOutput(ctx).String()
+ sandboxPath := shared.TempDirForOutDir(buildDir)
+
+ // recall that Sprintf replaces percent sign expressions, whereas dollar signs expressions remain as written,
+ // to be replaced later by ninja_strings.go
+ depfilePlaceholder := ""
+ if Bool(g.properties.Depfile) {
+ depfilePlaceholder = "$depfileArgs"
+ }
+
+ // Escape the command for the shell
+ rawCommand = "'" + strings.Replace(rawCommand, "'", `'\''`, -1) + "'"
+ g.rawCommands = append(g.rawCommands, rawCommand)
+ sandboxCommand := fmt.Sprintf("rm -rf %s && $sboxCmd --sandbox-path %s --output-root %s -c %s %s $allouts",
+ task.genDir, sandboxPath, task.genDir, rawCommand, depfilePlaceholder)
+
+ ruleParams := blueprint.RuleParams{
+ Command: sandboxCommand,
+ CommandDeps: []string{"$sboxCmd"},
+ }
+ args := []string{"allouts"}
+ if Bool(g.properties.Depfile) {
+ ruleParams.Deps = blueprint.DepsGCC
+ args = append(args, "depfileArgs")
+ }
+ name := "generator"
+ if task.shards > 1 {
+ name += strconv.Itoa(task.shard)
+ }
+ rule := ctx.Rule(pctx, name, ruleParams, args...)
+
+ g.generateSourceFile(ctx, task, rule)
+
+ if len(task.copyTo) > 0 {
+ outputFiles = append(outputFiles, task.copyTo...)
+ copyFrom = append(copyFrom, task.out.Paths()...)
+ zipArgs.WriteString(" -C " + task.genDir.String())
+ zipArgs.WriteString(android.JoinWithPrefix(task.out.Strings(), " -f "))
+ } else {
+ outputFiles = append(outputFiles, task.out...)
+ }
}
- if Bool(g.properties.Depfile) && !referencedDepfile {
- ctx.PropertyErrorf("cmd", "specified depfile=true but did not include a reference to '${depfile}' in cmd")
+ if len(copyFrom) > 0 {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: gensrcsMerge,
+ Implicits: copyFrom,
+ Outputs: outputFiles,
+ Args: map[string]string{
+ "zipArgs": zipArgs.String(),
+ "tmpZip": android.PathForModuleGen(ctx, g.subDir+".zip").String(),
+ "genDir": android.PathForModuleGen(ctx, g.subDir).String(),
+ },
+ })
}
- // tell the sbox command which directory to use as its sandbox root
- buildDir := android.PathForOutput(ctx).String()
- sandboxPath := shared.TempDirForOutDir(buildDir)
+ g.outputFiles = outputFiles.Paths()
- // recall that Sprintf replaces percent sign expressions, whereas dollar signs expressions remain as written,
- // to be replaced later by ninja_strings.go
- depfilePlaceholder := ""
- if Bool(g.properties.Depfile) {
- depfilePlaceholder = "$depfileArgs"
+ // For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
+ // the genrules on AOSP. That will make things simpler to look at the graph in the common
+ // case. For larger sets of outputs, inject a phony target in between to limit ninja file
+ // growth.
+ if len(g.outputFiles) <= 6 {
+ g.outputDeps = g.outputFiles
+ } else {
+ phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: blueprint.Phony,
+ Output: phonyFile,
+ Inputs: g.outputFiles,
+ })
+
+ g.outputDeps = android.Paths{phonyFile}
}
- genDir := android.PathForModuleGen(ctx)
- // Escape the command for the shell
- rawCommand = "'" + strings.Replace(rawCommand, "'", `'\''`, -1) + "'"
- g.rawCommand = rawCommand
- sandboxCommand := fmt.Sprintf("$sboxCmd --sandbox-path %s --output-root %s -c %s %s $allouts",
- sandboxPath, genDir, rawCommand, depfilePlaceholder)
-
- ruleParams := blueprint.RuleParams{
- Command: sandboxCommand,
- CommandDeps: []string{"$sboxCmd"},
- }
- args := []string{"allouts"}
- if Bool(g.properties.Depfile) {
- ruleParams.Deps = blueprint.DepsGCC
- args = append(args, "depfileArgs")
- }
- g.rule = ctx.Rule(pctx, "generator", ruleParams, args...)
-
- g.generateSourceFile(ctx, task)
-
}
-func (g *Module) generateSourceFile(ctx android.ModuleContext, task generateTask) {
+func (g *Module) generateSourceFile(ctx android.ModuleContext, task generateTask, rule blueprint.Rule) {
desc := "generate"
if len(task.out) == 0 {
ctx.ModuleErrorf("must have at least one output file")
@@ -405,9 +471,13 @@
depFile = android.PathForModuleGen(ctx, task.out[0].Rel()+".d")
}
+ if task.shards > 1 {
+ desc += " " + strconv.Itoa(task.shard)
+ }
+
params := android.BuildParams{
- Rule: g.rule,
- Description: "generate",
+ Rule: rule,
+ Description: desc,
Output: task.out[0],
ImplicitOutputs: task.out[1:],
Inputs: task.in,
@@ -422,28 +492,6 @@
}
ctx.Build(pctx, params)
-
- for _, outputFile := range task.out {
- g.outputFiles = append(g.outputFiles, outputFile)
- }
-
- // For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
- // the genrules on AOSP. That will make things simpler to look at the graph in the common
- // case. For larger sets of outputs, inject a phony target in between to limit ninja file
- // growth.
- if len(task.out) <= 6 {
- g.outputDeps = g.outputFiles
- } else {
- phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
-
- ctx.Build(pctx, android.BuildParams{
- Rule: blueprint.Phony,
- Output: phonyFile,
- Inputs: g.outputFiles,
- })
-
- g.outputDeps = android.Paths{phonyFile}
- }
}
// Collect information for opening IDE project files in java/jdeps.go.
@@ -465,7 +513,7 @@
SubName: g.subName,
Extra: []android.AndroidMkExtraFunc{
func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=", strings.Join(g.outputFiles.Strings(), " "))
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=", strings.Join(g.outputDeps.Strings(), " "))
},
},
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
@@ -502,47 +550,80 @@
func NewGenSrcs() *Module {
properties := &genSrcsProperties{}
- taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) generateTask {
- commands := []string{}
- outFiles := android.WritablePaths{}
- genDir := android.PathForModuleGen(ctx)
- sandboxOuts := []string{}
- for _, in := range srcFiles {
- outFile := android.GenPathWithExt(ctx, "", in, String(properties.Output_extension))
- outFiles = append(outFiles, outFile)
+ taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
+ genDir := android.PathForModuleGen(ctx, "gensrcs")
+ shardSize := defaultShardSize
+ if s := properties.Shard_size; s != nil {
+ shardSize = int(*s)
+ }
- sandboxOutfile := pathToSandboxOut(outFile, genDir)
- sandboxOuts = append(sandboxOuts, sandboxOutfile)
+ shards := android.ShardPaths(srcFiles, shardSize)
+ var generateTasks []generateTask
- command, err := android.Expand(rawCommand, func(name string) (string, error) {
- switch name {
- case "in":
- return in.String(), nil
- case "out":
- return sandboxOutfile, nil
- default:
- return "$(" + name + ")", nil
- }
- })
- if err != nil {
- ctx.PropertyErrorf("cmd", err.Error())
+ for i, shard := range shards {
+ var commands []string
+ var outFiles android.WritablePaths
+ var copyTo android.WritablePaths
+ var shardDir android.WritablePath
+ var sandboxOuts []string
+
+ if len(shards) > 1 {
+ shardDir = android.PathForModuleGen(ctx, strconv.Itoa(i))
+ } else {
+ shardDir = genDir
}
- // escape the command in case for example it contains '#', an odd number of '"', etc
- command = fmt.Sprintf("bash -c %v", proptools.ShellEscape(command))
- commands = append(commands, command)
- }
- fullCommand := strings.Join(commands, " && ")
+ for _, in := range shard {
+ outFile := android.GenPathWithExt(ctx, "gensrcs", in, String(properties.Output_extension))
+ sandboxOutfile := pathToSandboxOut(outFile, genDir)
- return generateTask{
- in: srcFiles,
- out: outFiles,
- sandboxOuts: sandboxOuts,
- cmd: fullCommand,
+ if len(shards) > 1 {
+ shardFile := android.GenPathWithExt(ctx, strconv.Itoa(i), in, String(properties.Output_extension))
+ copyTo = append(copyTo, outFile)
+ outFile = shardFile
+ }
+
+ outFiles = append(outFiles, outFile)
+ sandboxOuts = append(sandboxOuts, sandboxOutfile)
+
+ command, err := android.Expand(rawCommand, func(name string) (string, error) {
+ switch name {
+ case "in":
+ return in.String(), nil
+ case "out":
+ return sandboxOutfile, nil
+ default:
+ return "$(" + name + ")", nil
+ }
+ })
+ if err != nil {
+ ctx.PropertyErrorf("cmd", err.Error())
+ }
+
+ // escape the command in case for example it contains '#', an odd number of '"', etc
+ command = fmt.Sprintf("bash -c %v", proptools.ShellEscape(command))
+ commands = append(commands, command)
+ }
+ fullCommand := strings.Join(commands, " && ")
+
+ generateTasks = append(generateTasks, generateTask{
+ in: shard,
+ out: outFiles,
+ copyTo: copyTo,
+ genDir: shardDir,
+ sandboxOuts: sandboxOuts,
+ cmd: fullCommand,
+ shard: i,
+ shards: len(shards),
+ })
}
+
+ return generateTasks
}
- return generatorFactory(taskGenerator, properties)
+ g := generatorFactory(taskGenerator, properties)
+ g.subDir = "gensrcs"
+ return g
}
func GenSrcsFactory() android.Module {
@@ -554,12 +635,17 @@
type genSrcsProperties struct {
// extension that will be substituted for each output file
Output_extension *string
+
+ // maximum number of files that will be passed on a single command line.
+ Shard_size *int64
}
+const defaultShardSize = 100
+
func NewGenRule() *Module {
properties := &genRuleProperties{}
- taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) generateTask {
+ taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
outs := make(android.WritablePaths, len(properties.Out))
sandboxOuts := make([]string, len(properties.Out))
genDir := android.PathForModuleGen(ctx)
@@ -567,12 +653,13 @@
outs[i] = android.PathForModuleGen(ctx, out)
sandboxOuts[i] = pathToSandboxOut(outs[i], genDir)
}
- return generateTask{
+ return []generateTask{{
in: srcFiles,
out: outs,
+ genDir: android.PathForModuleGen(ctx),
sandboxOuts: sandboxOuts,
cmd: rawCommand,
- }
+ }}
}
return generatorFactory(taskGenerator, properties)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 0b6952f..5ac0e8c 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -57,6 +57,7 @@
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(GenRuleFactory))
+ ctx.RegisterModuleType("gensrcs", android.ModuleFactoryAdaptor(GenSrcsFactory))
ctx.RegisterModuleType("genrule_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
ctx.RegisterModuleType("tool", android.ModuleFactoryAdaptor(toolFactory))
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@@ -109,6 +110,9 @@
"tool_file2": nil,
"in1": nil,
"in2": nil,
+ "in1.txt": nil,
+ "in2.txt": nil,
+ "in3.txt": nil,
}
for k, v := range fs {
@@ -491,11 +495,102 @@
}
gen := ctx.ModuleForTests("gen", "").Module().(*Module)
- if g, w := gen.rawCommand, "'"+test.expect+"'"; w != g {
+ if g, w := gen.rawCommands[0], "'"+test.expect+"'"; w != g {
t.Errorf("want %q, got %q", w, g)
}
})
}
+}
+
+func TestGenSrcs(t *testing.T) {
+ testcases := []struct {
+ name string
+ prop string
+
+ allowMissingDependencies bool
+
+ err string
+ cmds []string
+ deps []string
+ files []string
+ }{
+ {
+ name: "gensrcs",
+ prop: `
+ tools: ["tool"],
+ srcs: ["in1.txt", "in2.txt"],
+ cmd: "$(location) $(in) > $(out)",
+ `,
+ cmds: []string{
+ "'bash -c '\\''out/tool in1.txt > __SBOX_OUT_DIR__/in1.h'\\'' && bash -c '\\''out/tool in2.txt > __SBOX_OUT_DIR__/in2.h'\\'''",
+ },
+ deps: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h"},
+ files: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h"},
+ },
+ {
+ name: "shards",
+ prop: `
+ tools: ["tool"],
+ srcs: ["in1.txt", "in2.txt", "in3.txt"],
+ cmd: "$(location) $(in) > $(out)",
+ shard_size: 2,
+ `,
+ cmds: []string{
+ "'bash -c '\\''out/tool in1.txt > __SBOX_OUT_DIR__/in1.h'\\'' && bash -c '\\''out/tool in2.txt > __SBOX_OUT_DIR__/in2.h'\\'''",
+ "'bash -c '\\''out/tool in3.txt > __SBOX_OUT_DIR__/in3.h'\\'''",
+ },
+ deps: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h", buildDir + "/.intermediates/gen/gen/gensrcs/in3.h"},
+ files: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h", buildDir + "/.intermediates/gen/gen/gensrcs/in3.h"},
+ },
+ }
+
+ for _, test := range testcases {
+ t.Run(test.name, func(t *testing.T) {
+ config := android.TestArchConfig(buildDir, nil)
+ bp := "gensrcs {\n"
+ bp += `name: "gen",` + "\n"
+ bp += `output_extension: "h",` + "\n"
+ bp += test.prop
+ bp += "}\n"
+
+ ctx := testContext(config, bp, nil)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ if errs == nil {
+ _, errs = ctx.PrepareBuildActions(config)
+ }
+ if errs == nil && test.err != "" {
+ t.Fatalf("want error %q, got no error", test.err)
+ } else if errs != nil && test.err == "" {
+ android.FailIfErrored(t, errs)
+ } else if test.err != "" {
+ if len(errs) != 1 {
+ t.Errorf("want 1 error, got %d errors:", len(errs))
+ for _, err := range errs {
+ t.Errorf(" %s", err.Error())
+ }
+ t.FailNow()
+ }
+ if !strings.Contains(errs[0].Error(), test.err) {
+ t.Fatalf("want %q, got %q", test.err, errs[0].Error())
+ }
+ return
+ }
+
+ gen := ctx.ModuleForTests("gen", "").Module().(*Module)
+ if g, w := gen.rawCommands, test.cmds; !reflect.DeepEqual(w, g) {
+ t.Errorf("want %q, got %q", w, g)
+ }
+
+ if g, w := gen.outputDeps.Strings(), test.deps; !reflect.DeepEqual(w, g) {
+ t.Errorf("want deps %q, got %q", w, g)
+ }
+
+ if g, w := gen.outputFiles.Strings(), test.files; !reflect.DeepEqual(w, g) {
+ t.Errorf("want files %q, got %q", w, g)
+ }
+ })
+ }
}
@@ -529,8 +624,8 @@
gen := ctx.ModuleForTests("gen", "").Module().(*Module)
expectedCmd := "'cp ${in} __SBOX_OUT_FILES__'"
- if gen.rawCommand != expectedCmd {
- t.Errorf("Expected cmd: %q, actual: %q", expectedCmd, gen.rawCommand)
+ if gen.rawCommands[0] != expectedCmd {
+ t.Errorf("Expected cmd: %q, actual: %q", expectedCmd, gen.rawCommands[0])
}
expectedSrcs := []string{"in1"}
diff --git a/go.mod b/go.mod
index cc328e0..1483a31 100644
--- a/go.mod
+++ b/go.mod
@@ -7,3 +7,5 @@
replace github.com/golang/protobuf v0.0.0 => ../../external/golang-protobuf
replace github.com/google/blueprint v0.0.0 => ../blueprint
+
+go 1.13
diff --git a/java/aar.go b/java/aar.go
index 6a883d3..6426ac3 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -520,6 +520,10 @@
return proptools.StringDefault(a.properties.Sdk_version, defaultSdkVersion(a))
}
+func (a *AARImport) systemModules() string {
+ return ""
+}
+
func (a *AARImport) minSdkVersion() string {
if a.properties.Min_sdk_version != nil {
return *a.properties.Min_sdk_version
diff --git a/java/androidmk.go b/java/androidmk.go
index bc61297..5067e2f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -598,6 +598,18 @@
fmt.Fprintln(w, "droidcore: checkapi")
}
}
+ if dstubs.apiLintTimestamp != nil {
+ fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-api-lint")
+ fmt.Fprintln(w, dstubs.Name()+"-api-lint:",
+ dstubs.apiLintTimestamp.String())
+
+ fmt.Fprintln(w, ".PHONY: checkapi")
+ fmt.Fprintln(w, "checkapi:",
+ dstubs.apiLintTimestamp.String())
+
+ fmt.Fprintln(w, ".PHONY: droidcore")
+ fmt.Fprintln(w, "droidcore: checkapi")
+ }
if dstubs.checkNullabilityWarningsTimestamp != nil {
fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-nullability-warnings")
fmt.Fprintln(w, dstubs.Name()+"-check-nullability-warnings:",
diff --git a/java/app.go b/java/app.go
index 3ee8b8d..e033661 100644
--- a/java/app.go
+++ b/java/app.go
@@ -126,7 +126,7 @@
// the install APK name is normally the same as the module name, but can be overridden with PRODUCT_PACKAGE_NAME_OVERRIDES.
installApkName string
- installDir android.OutputPath
+ installDir android.InstallPath
onDeviceDir string
@@ -773,7 +773,7 @@
usesLibrary usesLibrary
- installPath android.OutputPath
+ installPath android.InstallPath
}
type AndroidAppImportProperties struct {
diff --git a/java/config/config.go b/java/config/config.go
index ce62b93..f418ee7 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -86,6 +86,14 @@
// This is set up and guaranteed by soong_ui
return ctx.Config().Getenv("ANDROID_JAVA_HOME")
})
+ pctx.VariableFunc("JlinkVersion", func(ctx android.PackageVarContext) string {
+ switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN") {
+ case "true":
+ return "11"
+ default:
+ return "9"
+ }
+ })
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
pctx.SourcePathVariableWithEnvOverride("JavacCmd",
diff --git a/java/config/makevars.go b/java/config/makevars.go
index c40f4fc..2fa6f89 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -38,6 +38,7 @@
ctx.Strict("ANDROID_JAVA_HOME", "${JavaHome}")
ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}")
ctx.Strict("ANDROID_JAVA9_HOME", "prebuilts/jdk/jdk9/${hostPrebuiltTag}")
+ ctx.Strict("ANDROID_JAVA11_HOME", "prebuilts/jdk/jdk11/${hostPrebuiltTag}")
ctx.Strict("ANDROID_JAVA_TOOLCHAIN", "${JavaToolchain}")
ctx.Strict("JAVA", "${JavaCmd} ${JavaVmFlags}")
ctx.Strict("JAVAC", "${JavacCmd} ${JavacVmFlags}")
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..3b581cb 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -67,9 +67,15 @@
// If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
Installable *bool
- // if not blank, set to the version of the sdk to compile against
+ // if not blank, set to the version of the sdk to compile against.
+ // Defaults to compiling against the current platform.
Sdk_version *string `android:"arch_variant"`
+ // When targeting 1.9 and above, override the modules to use with --system,
+ // otherwise provides defaults libraries to add to the bootclasspath.
+ // Defaults to "none"
+ System_modules *string
+
Aidl struct {
// Top level directories to pass to aidl tool
Include_dirs []string
@@ -238,6 +244,16 @@
// do not perform API check against Last_released, in the case that both two specified API
// files by Last_released are modules which don't exist.
Ignore_missing_latest_api *bool `blueprint:"mutated"`
+
+ Api_lint struct {
+ Enabled *bool
+
+ // If set, performs api_lint on any new APIs not found in the given signature file
+ New_since *string `android:"path"`
+
+ // If not blank, path to the baseline txt file for approved API lint violations.
+ Baseline_file *string `android:"path"`
+ }
}
// user can specify the version of previous released API file in order to do compatibility check.
@@ -391,6 +407,10 @@
return proptools.StringDefault(j.properties.Sdk_version, defaultSdkVersion(j))
}
+func (j *Javadoc) systemModules() string {
+ return proptools.String(j.properties.System_modules)
+}
+
func (j *Javadoc) minSdkVersion() string {
return j.sdkVersion()
}
@@ -417,6 +437,10 @@
}
ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.modules...)
}
+ } else if sdkDep.systemModules != "" {
+ // Add the system modules to both the system modules and bootclasspath.
+ ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
+ ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.systemModules)
}
}
@@ -461,14 +485,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 +501,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
}
@@ -498,6 +528,10 @@
case bootClasspathTag:
if dep, ok := module.(Dependency); ok {
deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
+ } else if sm, ok := module.(*SystemModules); ok {
+ // A system modules dependency has been added to the bootclasspath
+ // so add its libs to the bootclasspath.
+ deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...)
} else {
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
}
@@ -1148,6 +1182,7 @@
checkCurrentApiTimestamp android.WritablePath
updateCurrentApiTimestamp android.WritablePath
checkLastReleasedApiTimestamp android.WritablePath
+ apiLintTimestamp android.WritablePath
checkNullabilityWarningsTimestamp android.WritablePath
@@ -1484,6 +1519,57 @@
// Create rule for apicheck
+ if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().IsPdkBuild() {
+ rule := android.NewRuleBuilder()
+ rule.Command().Text("( true")
+
+ srcJarDir := android.PathForModuleOut(ctx, "api_lint", "srcjars")
+ srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
+
+ cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
+ deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
+
+ cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles)
+
+ newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
+ if newSince.Valid() {
+ cmd.FlagWithInput("--api-lint ", newSince.Path())
+ } else {
+ cmd.Flag("--api-lint")
+ }
+
+ d.inclusionAnnotationsFlags(ctx, cmd)
+ d.mergeAnnoDirFlags(ctx, cmd)
+
+ baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
+ updatedBaselineOutput := android.PathForModuleOut(ctx, "api_lint_baseline.txt")
+ d.apiLintTimestamp = android.PathForModuleOut(ctx, "api_lint.timestamp")
+
+ if baselineFile.Valid() {
+ cmd.FlagWithInput("--baseline ", baselineFile.Path())
+ cmd.FlagWithOutput("--update-baseline ", updatedBaselineOutput)
+ }
+
+ zipSyncCleanupCmd(rule, srcJarDir)
+
+ msg := fmt.Sprintf(`\n******************************\n`+
+ `Your API changes are triggering API Lint warnings or errors.\n\n`+
+ `To make these errors go away, you have two choices:\n`+
+ ` 1. You can suppress the errors with @SuppressLint(\"<id>\").\n\n`+
+ ` 2. You can update the baseline by executing the following command:\n`+
+ ` cp \"$PWD/%s\" \"$PWD/%s\"\n\n`+
+ `******************************\n`, updatedBaselineOutput, baselineFile.Path())
+ rule.Command().
+ Text("touch").Output(d.apiLintTimestamp).
+ Text(") || (").
+ Text("echo").Flag("-e").Flag(`"` + msg + `"`).
+ Text("; exit 38").
+ Text(")")
+
+ rule.Build(pctx, ctx, "metalavaApiLint", "metalava API lint")
+
+ }
+
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") &&
!ctx.Config().IsPdkBuild() {
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..52f3c11 100644
--- a/java/java.go
+++ b/java/java.go
@@ -270,7 +270,8 @@
Proguard_flags_files []string `android:"path"`
}
- // When targeting 1.9, override the modules to use with --system
+ // When targeting 1.9 and above, override the modules to use with --system,
+ // otherwise provides defaults libraries to add to the bootclasspath.
System_modules *string
UncompressDex bool `blueprint:"mutated"`
@@ -347,8 +348,8 @@
// list of SDK lib names that this java moudule is exporting
exportedSdkLibs []string
- // list of source files, collected from compiledJavaSrcs and compiledSrcJars
- // filter out Exclude_srcs, will be used by android.IDEInfo struct
+ // list of source files, collected from srcFiles with uniqie java and all kt files,
+ // will be used by android.IDEInfo struct
expandIDEInfoCompiledSrcs []string
// expanded Jarjar_rules
@@ -457,7 +458,10 @@
type sdkDep struct {
useModule, useFiles, useDefaultLibs, invalidVersion bool
- modules []string
+ modules []string
+
+ // The default system modules to use. Will be an empty string if no system
+ // modules are to be used.
systemModules string
frameworkResModule string
@@ -496,6 +500,10 @@
return proptools.StringDefault(j.deviceProperties.Sdk_version, defaultSdkVersion(j))
}
+func (j *Module) systemModules() string {
+ return proptools.String(j.deviceProperties.System_modules)
+}
+
func (j *Module) minSdkVersion() string {
if j.deviceProperties.Min_sdk_version != nil {
return *j.deviceProperties.Min_sdk_version
@@ -528,13 +536,10 @@
ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...)
}
}
- } else if j.deviceProperties.System_modules == nil {
- ctx.PropertyErrorf("sdk_version",
- `system_modules is required to be set when sdk_version is "none", did you mean "core_platform"`)
- } else if *j.deviceProperties.System_modules != "none" {
+ } else if sdkDep.systemModules != "" {
// Add the system modules to both the system modules and bootclasspath.
- ctx.AddVariationDependencies(nil, systemModulesTag, *j.deviceProperties.System_modules)
- ctx.AddVariationDependencies(nil, bootClasspathTag, *j.deviceProperties.System_modules)
+ ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
+ ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.systemModules)
}
if ctx.ModuleName() == "android_stubs_current" ||
ctx.ModuleName() == "android_system_stubs_current" ||
@@ -1032,9 +1037,6 @@
srcJars = append(srcJars, aaptSrcJar)
}
- // Collect source files and filter out Exclude_srcs that IDEInfo struct will use
- j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.Strings()...)
-
if j.properties.Jarjar_rules != nil {
j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
}
@@ -1051,6 +1053,9 @@
}
}
+ // Collect .java files for AIDEGen
+ j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
+
var kotlinJars android.Paths
if srcFiles.HasExt(".kt") {
@@ -1075,6 +1080,9 @@
kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
+ // Collect .kt files for AIDEGen
+ j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
+
flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
@@ -1795,7 +1803,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.go b/java/sdk.go
index 3451774..c6a9a73 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -39,6 +39,8 @@
type sdkContext interface {
// sdkVersion returns the sdk_version property of the current module, or an empty string if it is not set.
sdkVersion() string
+ // systemModules returns the system_modules property of the current module, or an empty string if it is not set.
+ systemModules() string
// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
minSdkVersion() string
// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
@@ -185,8 +187,18 @@
frameworkResModule: "framework-res",
}
case "none":
+ systemModules := sdkContext.systemModules()
+ if systemModules == "" {
+ ctx.PropertyErrorf("sdk_version",
+ `system_modules is required to be set to a non-empty value when sdk_version is "none", did you mean sdk_version: "core_platform"?`)
+ } else if systemModules == "none" {
+ // Normalize no system modules to an empty string.
+ systemModules = ""
+ }
+
return sdkDep{
noStandardLibs: true,
+ systemModules: systemModules,
}
case "core_platform":
return sdkDep{
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/java/system_modules.go b/java/system_modules.go
index 43e4e11..b56a401 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -36,13 +36,15 @@
var (
jarsTosystemModules = pctx.AndroidStaticRule("jarsTosystemModules", blueprint.RuleParams{
Command: `rm -rf ${outDir} ${workDir} && mkdir -p ${workDir}/jmod && ` +
- `${moduleInfoJavaPath} ${moduleName} $in > ${workDir}/module-info.java && ` +
+ `${moduleInfoJavaPath} java.base $in > ${workDir}/module-info.java && ` +
`${config.JavacCmd} --system=none --patch-module=java.base=${classpath} ${workDir}/module-info.java && ` +
`${config.SoongZipCmd} -jar -o ${workDir}/classes.jar -C ${workDir} -f ${workDir}/module-info.class && ` +
`${config.MergeZipsCmd} -j ${workDir}/module.jar ${workDir}/classes.jar $in && ` +
- `${config.JmodCmd} create --module-version 9 --target-platform android ` +
- ` --class-path ${workDir}/module.jar ${workDir}/jmod/${moduleName}.jmod && ` +
- `${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules ${moduleName} --output ${outDir} ` +
+ // Note: The version of the java.base module created must match the version
+ // of the jlink tool which consumes it.
+ `${config.JmodCmd} create --module-version ${config.JlinkVersion} --target-platform android ` +
+ ` --class-path ${workDir}/module.jar ${workDir}/jmod/java.base.jmod && ` +
+ `${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules java.base --output ${outDir} ` +
// Note: The system-modules jlink plugin is disabled because (a) it is not
// useful on Android, and (b) it causes errors with later versions of jlink
// when the jdk.internal.module is absent from java.base (as it is here).
@@ -58,10 +60,10 @@
"${config.JrtFsJar}",
},
},
- "moduleName", "classpath", "outDir", "workDir")
+ "classpath", "outDir", "workDir")
)
-func TransformJarsToSystemModules(ctx android.ModuleContext, moduleName string, jars android.Paths) (android.Path, android.Paths) {
+func TransformJarsToSystemModules(ctx android.ModuleContext, jars android.Paths) (android.Path, android.Paths) {
outDir := android.PathForModuleOut(ctx, "system")
workDir := android.PathForModuleOut(ctx, "modules")
outputFile := android.PathForModuleOut(ctx, "system/lib/modules")
@@ -77,10 +79,9 @@
Outputs: outputs,
Inputs: jars,
Args: map[string]string{
- "moduleName": moduleName,
- "classpath": strings.Join(jars.Strings(), ":"),
- "workDir": workDir.String(),
- "outDir": outDir.String(),
+ "classpath": strings.Join(jars.Strings(), ":"),
+ "workDir": workDir.String(),
+ "outDir": outDir.String(),
},
})
@@ -123,7 +124,7 @@
system.headerJars = jars
- system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, "java.base", jars)
+ system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, jars)
}
func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) {
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/compiler.go b/rust/compiler.go
index 3bfef76..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,12 +119,12 @@
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())
@@ -173,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 ae50804..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,7 @@
"libtest",
}
- DefaultDenyWarnings = proptools.BoolPtr(true)
+ DefaultDenyWarnings = true
GlobalRustFlags = []string{
"--remap-path-prefix $$(pwd)=",
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 0a2b510..1dbeb26 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -107,6 +107,8 @@
productOut("obj/NOTICE_FILES"),
productOut("obj/PACKAGING"),
productOut("ramdisk"),
+ productOut("debug_ramdisk"),
+ productOut("test_harness_ramdisk"),
productOut("recovery"),
productOut("root"),
productOut("system"),
diff --git a/ui/build/config.go b/ui/build/config.go
index def3345..919b9ce 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -214,10 +214,14 @@
// Configure Java-related variables, including adding it to $PATH
java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
+ java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
javaHome := func() string {
if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
return override
}
+ if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 == "true" {
+ return java11Home
+ }
return java9Home
}()
absJavaHome := absPath(ctx, javaHome)
@@ -228,11 +232,13 @@
if path, ok := ret.environ.Get("PATH"); ok && path != "" {
newPath = append(newPath, path)
}
+
ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
ret.environ.Set("JAVA_HOME", absJavaHome)
ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
+ ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
outDir := ret.OutDir()
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 82b2750..4270bb1 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"
@@ -40,6 +42,7 @@
soongUiVars := map[string]func() string{
"OUT_DIR": func() string { return config.OutDir() },
"DIST_DIR": func() string { return config.DistDir() },
+ "TMPDIR": func() string { return absPath(ctx, config.TempDir()) },
}
makeVars := make([]string, 0, len(vars))
@@ -51,7 +54,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
@@ -209,6 +222,7 @@
"DEFAULT_WARNING_BUILD_MODULE_TYPES",
"DEFAULT_ERROR_BUILD_MODULE_TYPES",
"BUILD_BROKEN_PREBUILT_ELF_FILES",
+ "BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW",
"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/ui/build/paths/config.go b/ui/build/paths/config.go
index e44600e..1af816b 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -122,6 +122,9 @@
"pgrep": LinuxOnlyPrebuilt,
"pkill": LinuxOnlyPrebuilt,
"ps": LinuxOnlyPrebuilt,
+
+ // The toybox xargs is currently breaking the mac build.
+ "xargs": LinuxOnlyPrebuilt,
}
func init() {
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())
}