Merge "Singleton build rule for merged compat config."
diff --git a/Android.bp b/Android.bp
index 7576102..9403b26 100644
--- a/Android.bp
+++ b/Android.bp
@@ -155,6 +155,7 @@
"cc/androidmk.go",
"cc/builder.go",
"cc/cc.go",
+ "cc/ccdeps.go",
"cc/check.go",
"cc/coverage.go",
"cc/gen.go",
@@ -507,11 +508,13 @@
],
srcs: [
"sdk/bp.go",
+ "sdk/exports.go",
"sdk/sdk.go",
"sdk/update.go",
],
testSrcs: [
"sdk/cc_sdk_test.go",
+ "sdk/exports_test.go",
"sdk/java_sdk_test.go",
"sdk/sdk_test.go",
"sdk/testing.go",
diff --git a/android/apex.go b/android/apex.go
index 1b0412b..8482dc2 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -185,6 +185,8 @@
}
variations = append(variations, m.apexVariations...)
+ defaultVariation := ""
+ mctx.SetDefaultDependencyVariation(&defaultVariation)
modules := mctx.CreateVariations(variations...)
for i, m := range modules {
if availableForPlatform && i == 0 {
diff --git a/android/arch.go b/android/arch.go
index 131d3b9..b5b8a8f 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1602,6 +1602,15 @@
}
}
+func getAmlAbisConfig() []archConfig {
+ return []archConfig{
+ {"arm", "armv7-a", "", []string{"armeabi-v7a"}},
+ {"arm64", "armv8-a", "", []string{"arm64-v8a"}},
+ {"x86", "", "", []string{"x86"}},
+ {"x86_64", "", "", []string{"x86_64"}},
+ }
+}
+
func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) {
var ret []Target
diff --git a/android/config.go b/android/config.go
index a9833da..101f457 100644
--- a/android/config.go
+++ b/android/config.go
@@ -364,6 +364,8 @@
archConfig = getMegaDeviceConfig()
} else if config.NdkAbis() {
archConfig = getNdkAbisConfig()
+ } else if config.AmlAbis() {
+ archConfig = getAmlAbisConfig()
}
if archConfig != nil {
@@ -946,6 +948,10 @@
return String(c.config.productVariables.Platform_vndk_version)
}
+func (c *deviceConfig) ProductVndkVersion() string {
+ return String(c.config.productVariables.ProductVndkVersion)
+}
+
func (c *deviceConfig) ExtraVndkVersions() []string {
return c.config.productVariables.ExtraVndkVersions
}
@@ -1122,6 +1128,10 @@
return Bool(c.productVariables.Ndk_abis)
}
+func (c *config) AmlAbis() bool {
+ return Bool(c.productVariables.Aml_abis)
+}
+
func (c *config) ExcludeDraftNdkApis() bool {
return Bool(c.productVariables.Exclude_draft_ndk_apis)
}
diff --git a/android/hooks.go b/android/hooks.go
index 604cb9c..0e0f5a4 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -33,24 +33,11 @@
CreateModule(ModuleFactory, ...interface{}) Module
}
-// Arch hooks are run after the module has been split into architecture variants, and can be used
-// to add architecture-specific properties.
-type ArchHookContext interface {
- BaseModuleContext
- AppendProperties(...interface{})
- PrependProperties(...interface{})
-}
-
func AddLoadHook(m blueprint.Module, hook func(LoadHookContext)) {
h := &m.(Module).base().hooks
h.load = append(h.load, hook)
}
-func AddArchHook(m blueprint.Module, hook func(ArchHookContext)) {
- h := &m.(Module).base().hooks
- h.arch = append(h.arch, hook)
-}
-
func (x *hooks) runLoadHooks(ctx LoadHookContext, m *ModuleBase) {
if len(x.load) > 0 {
for _, x := range x.load {
@@ -62,17 +49,6 @@
}
}
-func (x *hooks) runArchHooks(ctx ArchHookContext, m *ModuleBase) {
- if len(x.arch) > 0 {
- for _, x := range x.arch {
- x(ctx)
- if ctx.Failed() {
- return
- }
- }
- }
-}
-
type InstallHookContext interface {
ModuleContext
Path() InstallPath
@@ -119,7 +95,6 @@
type hooks struct {
load []func(LoadHookContext)
- arch []func(ArchHookContext)
install []func(InstallHookContext)
}
@@ -137,12 +112,3 @@
m.base().hooks.runLoadHooks(loadHookCtx, m.base())
}
}
-
-func archHookMutator(ctx TopDownMutatorContext) {
- if m, ok := ctx.Module().(Module); ok {
- // Cast through *topDownMutatorContext because AppendProperties is implemented
- // on *topDownMutatorContext but not exposed through TopDownMutatorContext
- var archHookCtx ArchHookContext = ctx.(*topDownMutatorContext)
- m.base().hooks.runArchHooks(archHookCtx, m.base())
- }
-}
diff --git a/android/mutator.go b/android/mutator.go
index c2bae44..709d9c0 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -89,7 +89,6 @@
ctx.BottomUp("os", osMutator).Parallel()
ctx.BottomUp("image", imageMutator).Parallel()
ctx.BottomUp("arch", archMutator).Parallel()
- ctx.TopDown("arch_hooks", archHookMutator).Parallel()
}
var preDeps = []RegisterMutatorFunc{
diff --git a/android/neverallow.go b/android/neverallow.go
index 48efb4f..cef73fb 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -136,9 +136,6 @@
"external/icu",
"external/okhttp",
"external/wycheproof",
-
- // Not really a core library but still needs access to same capabilities.
- "development",
}
// Core library constraints. The sdk_version: "none" can only be used in core library projects.
diff --git a/android/override_module.go b/android/override_module.go
index 45f7be0..5bc787b 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -155,11 +155,6 @@
// Overrides a base module with the given OverrideModule.
func (b *OverridableModuleBase) override(ctx BaseModuleContext, o OverrideModule) {
- // Adds the base module to the overrides property, if exists, of the overriding module. See the
- // comment on OverridableModuleBase.overridesProperty for details.
- if b.overridesProperty != nil {
- *b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName())
- }
for _, p := range b.overridableProperties {
for _, op := range o.getOverridingProperties() {
if proptools.TypeEqual(p, op) {
@@ -174,6 +169,11 @@
}
}
}
+ // Adds the base module to the overrides property, if exists, of the overriding module. See the
+ // comment on OverridableModuleBase.overridesProperty for details.
+ if b.overridesProperty != nil {
+ *b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName())
+ }
b.properties.OverriddenBy = o.Name()
}
diff --git a/android/paths.go b/android/paths.go
index 024432e..c841372 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -118,6 +118,9 @@
type WritablePath interface {
Path
+ // return the path to the build directory.
+ buildDir() string
+
// the writablePath method doesn't directly do anything,
// but it allows a struct to distinguish between whether or not it implements the WritablePath interface
writablePath()
@@ -848,7 +851,12 @@
return p
}
+func (p OutputPath) buildDir() string {
+ return p.config.buildDir
+}
+
var _ Path = OutputPath{}
+var _ WritablePath = OutputPath{}
// PathForOutput joins the provided paths and returns an OutputPath that is
// validated to not escape the build dir.
@@ -1151,6 +1159,13 @@
baseDir string // "../" for Make paths to convert "out/soong" to "out", "" for Soong paths
}
+func (p InstallPath) buildDir() string {
+ return p.config.buildDir
+}
+
+var _ Path = InstallPath{}
+var _ WritablePath = InstallPath{}
+
func (p InstallPath) writablePath() {}
func (p InstallPath) String() string {
@@ -1302,6 +1317,10 @@
func (p PhonyPath) writablePath() {}
+func (p PhonyPath) buildDir() string {
+ return p.config.buildDir
+}
+
var _ Path = PhonyPath{}
var _ WritablePath = PhonyPath{}
diff --git a/android/sdk.go b/android/sdk.go
index 7956434..9e6ad16 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -237,6 +237,9 @@
// The name of the member type property on an sdk module.
SdkPropertyName() string
+ // True if the member type supports the sdk/sdk_snapshot, false otherwise.
+ UsableWithSdkAndSdkSnapshot() bool
+
// Add dependencies from the SDK module to all the variants the member
// contributes to the SDK. The exact set of variants required is determined
// by the SDK and its properties. The dependencies must be added with the
@@ -262,14 +265,20 @@
BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember)
}
+// Base type for SdkMemberType implementations.
type SdkMemberTypeBase struct {
PropertyName string
+ SupportsSdk bool
}
func (b *SdkMemberTypeBase) SdkPropertyName() string {
return b.PropertyName
}
+func (b *SdkMemberTypeBase) UsableWithSdkAndSdkSnapshot() bool {
+ return b.SupportsSdk
+}
+
// Encapsulates the information about registered SdkMemberTypes.
type SdkMemberTypesRegistry struct {
// The list of types sorted by property name.
@@ -279,22 +288,8 @@
key OnceKey
}
-func (r *SdkMemberTypesRegistry) RegisteredTypes() []SdkMemberType {
- return r.list
-}
-
-func (r *SdkMemberTypesRegistry) UniqueOnceKey() OnceKey {
- // Use the pointer to the registry as the unique key.
- return NewCustomOnceKey(r)
-}
-
-// The set of registered SdkMemberTypes.
-var SdkMemberTypes = &SdkMemberTypesRegistry{}
-
-// Register an SdkMemberType object to allow them to be used in the sdk and sdk_snapshot module
-// types.
-func RegisterSdkMemberType(memberType SdkMemberType) {
- oldList := SdkMemberTypes.list
+func (r *SdkMemberTypesRegistry) copyAndAppend(memberType SdkMemberType) *SdkMemberTypesRegistry {
+ oldList := r.list
// Copy the slice just in case this is being read while being modified, e.g. when testing.
list := make([]SdkMemberType, 0, len(oldList)+1)
@@ -319,8 +314,33 @@
key := NewOnceKey(strings.Join(properties, "|"))
// Create a new registry so the pointer uniquely identifies the set of registered types.
- SdkMemberTypes = &SdkMemberTypesRegistry{
+ return &SdkMemberTypesRegistry{
list: list,
key: key,
}
}
+
+func (r *SdkMemberTypesRegistry) RegisteredTypes() []SdkMemberType {
+ return r.list
+}
+
+func (r *SdkMemberTypesRegistry) UniqueOnceKey() OnceKey {
+ // Use the pointer to the registry as the unique key.
+ return NewCustomOnceKey(r)
+}
+
+// The set of registered SdkMemberTypes, one for sdk module and one for module_exports.
+var ModuleExportsMemberTypes = &SdkMemberTypesRegistry{}
+var SdkMemberTypes = &SdkMemberTypesRegistry{}
+
+// Register an SdkMemberType object to allow them to be used in the sdk and sdk_snapshot module
+// types.
+func RegisterSdkMemberType(memberType SdkMemberType) {
+ // All member types are usable with module_exports.
+ ModuleExportsMemberTypes = ModuleExportsMemberTypes.copyAndAppend(memberType)
+
+ // Only those that explicitly indicate it are usable with sdk.
+ if memberType.UsableWithSdkAndSdkSnapshot() {
+ SdkMemberTypes = SdkMemberTypes.copyAndAppend(memberType)
+ }
+}
diff --git a/android/testing.go b/android/testing.go
index aaf98f5..4f0591b 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "path/filepath"
"regexp"
"strings"
"testing"
@@ -411,3 +412,33 @@
data.fillInData(config, bpPath, mod)
return data
}
+
+// Normalize the path for testing.
+//
+// If the path is relative to the build directory then return the relative path
+// to avoid tests having to deal with the dynamically generated build directory.
+//
+// Otherwise, return the supplied path as it is almost certainly a source path
+// that is relative to the root of the source tree.
+//
+// The build and source paths should be distinguishable based on their contents.
+func NormalizePathForTesting(path Path) string {
+ p := path.String()
+ if w, ok := path.(WritablePath); ok {
+ rel, err := filepath.Rel(w.buildDir(), p)
+ if err != nil {
+ panic(err)
+ }
+ return rel
+ }
+ return p
+}
+
+func NormalizePathsForTesting(paths Paths) []string {
+ var result []string
+ for _, path := range paths {
+ relative := NormalizePathForTesting(path)
+ result = append(result, relative)
+ }
+ return result
+}
diff --git a/android/variable.go b/android/variable.go
index 628408e..2bf84dd 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -288,6 +288,7 @@
Exclude_draft_ndk_apis *bool `json:",omitempty"`
Flatten_apex *bool `json:",omitempty"`
+ Aml_abis *bool `json:",omitempty"`
DexpreoptGlobalConfig *string `json:",omitempty"`
@@ -306,6 +307,8 @@
ProductPrivateSepolicyDirs []string `json:",omitempty"`
ProductCompatibleProperty *bool `json:",omitempty"`
+ ProductVndkVersion *string `json:",omitempty"`
+
TargetFSConfigGen []string `json:",omitempty"`
MissingUsesLibraries []string `json:",omitempty"`
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7d1a301..c42b348 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -181,7 +181,7 @@
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())
- fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(a.properties.Overrides, " "))
+ fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(a.overridableProperties.Overrides, " "))
if len(moduleNames) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " "))
}
diff --git a/apex/apex.go b/apex/apex.go
index f6997bf..b27b54e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -105,7 +105,8 @@
android.UpdateApexDependency(apexBundleName, depName, directDep)
}
- if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
+ if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
+ (directDep || am.DepIsInSameApex(mctx, child)) {
am.BuildForApex(apexBundleName)
return true
} else {
@@ -333,13 +334,6 @@
// also built with the SDKs specified here.
Uses_sdks []string
- // Names of modules to be overridden. Listed modules can only be other binaries
- // (in Make or Soong).
- // This does not completely prevent installation of the overridden binaries, but if both
- // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
- // from PRODUCT_PACKAGES.
- Overrides []string
-
// Whenever apex_payload.img of the APEX should include dm-verity hashtree.
// Should be only used in tests#.
Test_only_no_hashtree *bool
@@ -376,6 +370,13 @@
type overridableProperties struct {
// List of APKs to package inside APEX
Apps []string
+
+ // Names of modules to be overridden. Listed modules can only be other binaries
+ // (in Make or Soong).
+ // This does not completely prevent installation of the overridden binaries, but if both
+ // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
+ // from PRODUCT_PACKAGES.
+ Overrides []string
}
type apexPackaging int
@@ -884,18 +885,6 @@
return newApexFile(ctx, fileToCopy, lib.Name(), dirInApex, javaSharedLib, lib)
}
-func apexFileForPrebuiltJavaLibrary(ctx android.BaseModuleContext, java *java.Import) apexFile {
- dirInApex := "javalib"
- // The output is only one, but for some reason, ImplementationJars returns Paths, not Path
- implJars := java.ImplementationJars()
- if len(implJars) != 1 {
- panic(fmt.Errorf("java.ImplementationJars() must return single Path, but got: %s",
- strings.Join(implJars.Strings(), ", ")))
- }
- fileToCopy := implJars[0]
- return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
-}
-
func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt android.PrebuiltEtcModule, depName string) apexFile {
dirInApex := filepath.Join("etc", prebuilt.SubDir())
fileToCopy := prebuilt.OutputFile()
@@ -1036,20 +1025,13 @@
}
filesInfo = append(filesInfo, af)
- pf := sdkLib.PermissionFile()
- if pf == nil {
+ pf, _ := sdkLib.OutputFiles(".xml")
+ if len(pf) != 1 {
ctx.PropertyErrorf("java_libs", "%q failed to generate permission XML", depName)
return false
}
- filesInfo = append(filesInfo, newApexFile(ctx, pf, pf.Base(), "etc/permissions", etc, nil))
+ filesInfo = append(filesInfo, newApexFile(ctx, pf[0], pf[0].Base(), "etc/permissions", etc, nil))
return true // track transitive dependencies
- } else if javaLib, ok := child.(*java.Import); ok {
- af := apexFileForPrebuiltJavaLibrary(ctx, javaLib)
- if !af.Ok() {
- ctx.PropertyErrorf("java_libs", "%q does not have a jar output", depName)
- } else {
- filesInfo = append(filesInfo, af)
- }
} else {
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
@@ -1060,6 +1042,8 @@
return true // track transitive dependencies
} else if ap, ok := child.(*java.AndroidAppImport); ok {
filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+ } else if ap, ok := child.(*java.AndroidTestHelperApp); ok {
+ filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
} else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
@@ -1267,7 +1251,7 @@
android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitSdkAwareModule(module)
- android.InitOverridableModule(module, &module.properties.Overrides)
+ android.InitOverridableModule(module, &module.overridableProperties.Overrides)
return module
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e8dc9aa..0d929ed 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -286,8 +286,6 @@
ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
ctx.RegisterModuleType("override_apex", overrideApexFactory)
- ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
- ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
cc.RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
ctx.RegisterModuleType("cc_test", cc.TestFactory)
@@ -374,7 +372,7 @@
binaries: ["foo",],
}
},
- java_libs: ["myjar", "myprebuiltjar"],
+ java_libs: ["myjar"],
}
apex {
@@ -440,6 +438,7 @@
system_modules: "none",
compile_dex: true,
static_libs: ["myotherjar"],
+ libs: ["mysharedjar"],
}
java_library {
@@ -450,10 +449,12 @@
compile_dex: true,
}
- java_import {
- name: "myprebuiltjar",
- jars: ["prebuilt.jar"],
- installable: true,
+ java_library {
+ name: "mysharedjar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ compile_dex: true,
}
`)
@@ -472,7 +473,6 @@
// Ensure that apex variant is created for the direct dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("myprebuiltjar"), "android_common_myapex")
// Ensure that apex variant is created for the indirect dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
@@ -482,16 +482,19 @@
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
ensureContains(t, copyCmds, "image.apex/javalib/myjar.jar")
- ensureContains(t, copyCmds, "image.apex/javalib/myprebuiltjar.jar")
// .. but not for java libs
ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar")
+ ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar")
// Ensure that the platform variant ends with _shared or _common
ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared")
ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared")
ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common")
ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common")
- ensureListContains(t, ctx.ModuleVariantsForTests("myprebuiltjar"), "android_common")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mysharedjar"), "android_common")
+
+ // Ensure that dynamic dependency to java libs are not included
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("mysharedjar"), "android_common_myapex")
// Ensure that all symlinks are present.
found_foo_link_64 := false
@@ -711,9 +714,9 @@
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with the latest version of stubs for mylib2
- ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3_myapex/mylib2.so")
+ ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3/mylib2.so")
// ... and not linking to the non-stub (impl) variant of mylib2
- ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_myapex/mylib2.so")
+ ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
@@ -725,7 +728,7 @@
ensureNotContains(t, mylib2Cflags, "-include ")
// Ensure that genstub is invoked with --apex
- ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_3_myapex").Rule("genStubSrc").Args["flags"])
+ ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_3").Rule("genStubSrc").Args["flags"])
ensureExactContents(t, ctx, "myapex", []string{
"lib64/mylib.so",
@@ -791,11 +794,11 @@
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with version 10 of libfoo
- ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10_myapex/libfoo.so")
+ ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
// ... and not linking to the non-stub (impl) variant of libfoo
- ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_myapex/libfoo.so")
+ ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared/libfoo.so")
- libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_10_myapex").Rule("ld").Args["libFlags"]
+ libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_10").Rule("ld").Args["libFlags"]
// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
@@ -1007,9 +1010,9 @@
// For dependency to libc
// Ensure that mylib is linking with the latest version of stubs
- ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29_myapex/libc.so")
+ ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29/libc.so")
// ... and not linking to the non-stub (impl) variant
- ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_myapex/libc.so")
+ ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared/libc.so")
// ... Cflags from stub is correctly exported to mylib
ensureContains(t, mylibCFlags, "__LIBC_API__=29")
ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
@@ -1018,17 +1021,17 @@
// Ensure that mylib is linking with the non-stub (impl) variant
ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
// ... and not linking to the stub variant
- ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29_myapex/libm.so")
+ ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29/libm.so")
// ... and is not compiling with the stub
ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
// For dependency to libdl
// Ensure that mylib is linking with the specified version of stubs
- ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27_myapex/libdl.so")
+ ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27/libdl.so")
// ... and not linking to the other versions of stubs
- ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28_myapex/libdl.so")
- ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29_myapex/libdl.so")
+ ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28/libdl.so")
+ ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29/libdl.so")
// ... and not linking to the non-stub (impl) variant
ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
// ... Cflags from stub is correctly exported to mylib
@@ -1637,7 +1640,6 @@
"etc/vndkcore.libraries.VER.txt",
"etc/vndksp.libraries.VER.txt",
"etc/vndkprivate.libraries.VER.txt",
- "etc/vndkcorevariant.libraries.VER.txt",
})
}
@@ -1698,7 +1700,7 @@
func vndkLibrariesTxtFiles(vers ...string) (result string) {
for _, v := range vers {
if v == "current" {
- for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkcorevariant"} {
+ for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate"} {
result += `
vndk_libraries_txt {
name: "` + txt + `.libraries.txt",
@@ -2926,6 +2928,36 @@
ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AppFooPrivPrebuilt.apk")
}
+func TestApexWithTestHelperApp(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: [
+ "TesterHelpAppFoo",
+ ],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ android_test_helper_app {
+ name: "TesterHelpAppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ }
+
+ `)
+
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ apexRule := module.Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo/TesterHelpAppFoo.apk")
+}
+
func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
// libfoo's apex_available comes from cc_defaults
testApexError(t, `"myapex" .*: requires "libfoo" that is not available for the APEX`, `
@@ -3148,12 +3180,14 @@
name: "myapex",
key: "myapex.key",
apps: ["app"],
+ overrides: ["oldapex"],
}
override_apex {
name: "override_myapex",
base: "myapex",
apps: ["override_app"],
+ overrides: ["unknownapex"],
}
apex_key {
@@ -3206,6 +3240,7 @@
ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.override_myapex")
ensureContains(t, androidMk, "LOCAL_MODULE_STEM := override_myapex.apex")
+ ensureContains(t, androidMk, "LOCAL_OVERRIDES_MODULES := unknownapex myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := app.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := override_app.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex")
@@ -3266,8 +3301,8 @@
"etc/permissions/foo.xml",
})
// Permission XML should point to the activated path of impl jar of java_sdk_library
- genXMLCommand := ctx.ModuleForTests("foo", "android_common_myapex").Output("foo.xml").RuleParams.Command
- ensureContains(t, genXMLCommand, `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
+ xml := ctx.ModuleForTests("foo", "android_common_myapex").Output("foo.xml")
+ ensureContains(t, xml.Args["content"], `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
}
func TestRejectNonInstallableJavaLibrary(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index fe465f5..4a760b9 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -105,6 +105,7 @@
`${apexer} --force --manifest ${manifest} ` +
`--file_contexts ${file_contexts} ` +
`--canned_fs_config ${canned_fs_config} ` +
+ `--include_build_info ` +
`--payload_type image ` +
`--key ${key} ${opt_flags} ${image_dir} ${out} `,
CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
@@ -378,7 +379,7 @@
optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeFile.String()))
}
- if ctx.ModuleDir() != "system/apex/apexd/apexd_testdata" && a.testOnlyShouldSkipHashtreeGeneration() {
+ if ctx.ModuleDir() != "system/apex/apexd/apexd_testdata" && ctx.ModuleDir() != "system/apex/shim/build" && a.testOnlyShouldSkipHashtreeGeneration() {
ctx.PropertyErrorf("test_only_no_hashtree", "not available")
return
}
diff --git a/apex/vndk.go b/apex/vndk.go
index 43fcfcd..1f52d11 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -108,9 +108,8 @@
func makeCompatSymlinks(apexName string, ctx android.ModuleContext) (symlinks []string) {
// small helper to add symlink commands
addSymlink := func(target, dir, linkName string) {
- outDir := filepath.Join("$(PRODUCT_OUT)", dir)
- link := filepath.Join(outDir, linkName)
- symlinks = append(symlinks, "mkdir -p "+outDir+" && rm -rf "+link+" && ln -sf "+target+" "+link)
+ link := filepath.Join(dir, linkName)
+ symlinks = append(symlinks, "mkdir -p "+dir+" && rm -rf "+link+" && ln -sf "+target+" "+link)
}
// TODO(b/142911355): [VNDK APEX] Fix hard-coded references to /system/lib/vndk
@@ -121,12 +120,28 @@
// the name of vndk apex is formatted "com.android.vndk.v" + version
vndkVersion := strings.TrimPrefix(apexName, vndkApexNamePrefix)
if ctx.Config().Android64() {
- addSymlink("/apex/"+apexName+"/lib64", "/system/lib64", "vndk-sp-"+vndkVersion)
- addSymlink("/apex/"+apexName+"/lib64", "/system/lib64", "vndk-"+vndkVersion)
+ addSymlink("/apex/"+apexName+"/lib64", "$(TARGET_OUT)/lib64", "vndk-sp-"+vndkVersion)
+ addSymlink("/apex/"+apexName+"/lib64", "$(TARGET_OUT)/lib64", "vndk-"+vndkVersion)
}
if !ctx.Config().Android64() || ctx.DeviceConfig().DeviceSecondaryArch() != "" {
- addSymlink("/apex/"+apexName+"/lib", "/system/lib", "vndk-sp-"+vndkVersion)
- addSymlink("/apex/"+apexName+"/lib", "/system/lib", "vndk-"+vndkVersion)
+ addSymlink("/apex/"+apexName+"/lib", "$(TARGET_OUT)/lib", "vndk-sp-"+vndkVersion)
+ addSymlink("/apex/"+apexName+"/lib", "$(TARGET_OUT)/lib", "vndk-"+vndkVersion)
+ }
+ }
+
+ // http://b/121248172 - create a link from /system/usr/icu to
+ // /apex/com.android.i18n/etc/icu so that apps can find the ICU .dat file.
+ // A symlink can't overwrite a directory and the /system/usr/icu directory once
+ // existed so the required structure must be created whatever we find.
+ if apexName == "com.android.i18n" {
+ addSymlink("/apex/"+apexName+"/etc/icu", "$(TARGET_OUT)/usr", "icu")
+ }
+
+ // TODO(b/124106384): Clean up compat symlinks for ART binaries.
+ if strings.HasPrefix(apexName, "com.android.art.") {
+ artBinaries := []string{"dalvikvm", "dex2oat"}
+ for _, b := range artBinaries {
+ addSymlink("/apex/com.android.art/bin/"+b, "$(TARGET_OUT)/bin", b)
}
}
return
diff --git a/build_kzip.bash b/build_kzip.bash
index 1e0d48f..02b346d 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -15,8 +15,19 @@
# The extraction might fail for some source files, so run with -k and then check that
# sufficiently many files were generated.
-build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
declare -r out="${OUT_DIR:-out}"
+# Build extraction files for C++ and Java. Build `merge_zips` which we use later.
+build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
+#Build extraction file for Go files in build/soong directory.
+declare -r abspath_out=$(realpath "${out}")
+(cd build/soong;
+ ../../prebuilts/build-tools/linux-x86/bin/go_extractor \
+ --goroot="${PWD}/../../prebuilts/go/linux-x86" \
+ --rules=vnames.go.json \
+ --canonicalize_package_corpus \
+ --output "${abspath_out}/soong/all.go.kzip" \
+ ./... )
+
declare -r kzip_count=$(find "$out" -name '*.kzip' | wc -l)
(($kzip_count>100000)) || { printf "Too few kzip files were generated: %d\n" $kzip_count; exit 1; }
diff --git a/cc/androidmk.go b/cc/androidmk.go
index c1225bc..988ebd4 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -25,6 +25,7 @@
var (
nativeBridgeSuffix = ".native_bridge"
+ productSuffix = ".product"
vendorSuffix = ".vendor"
recoverySuffix = ".recovery"
)
@@ -37,7 +38,7 @@
Os() android.OsType
Host() bool
UseVndk() bool
- vndkVersion() string
+ VndkVersion() string
static() bool
InRecovery() bool
}
@@ -92,7 +93,7 @@
if c.UseVndk() {
fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
if c.IsVndk() && !c.static() {
- fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.vndkVersion())
+ 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() {
diff --git a/cc/cc.go b/cc/cc.go
index 14e7122..0c32225 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -215,8 +215,9 @@
PreventInstall bool `blueprint:"mutated"`
ApexesProvidingSharedLibs []string `blueprint:"mutated"`
- VndkVersion string `blueprint:"mutated"`
- SubName string `blueprint:"mutated"`
+ ImageVariationPrefix string `blueprint:"mutated"`
+ VndkVersion string `blueprint:"mutated"`
+ SubName string `blueprint:"mutated"`
// *.logtags files, to combine together in order to generate the /system/etc/event-log-tags
// file
@@ -228,7 +229,7 @@
// Set by imageMutator
CoreVariantNeeded bool `blueprint:"mutated"`
RecoveryVariantNeeded bool `blueprint:"mutated"`
- VendorVariants []string `blueprint:"mutated"`
+ ExtraVariants []string `blueprint:"mutated"`
// Allows this module to use non-APEX version of libraries. Useful
// for building binaries that are started before APEXes are activated.
@@ -242,20 +243,24 @@
type VendorProperties struct {
// whether this module should be allowed to be directly depended by other
// modules with `vendor: true`, `proprietary: true`, or `vendor_available:true`.
- // If set to true, two variants will be built separately, one like
- // normal, and the other limited to the set of libraries and headers
- // that are exposed to /vendor modules.
+ // In addition, this module should be allowed to be directly depended by
+ // product modules with `product_specific: true`.
+ // If set to true, three variants will be built separately, one like
+ // normal, another limited to the set of libraries and headers
+ // that are exposed to /vendor modules, and the other to /product modules.
//
- // The vendor variant may be used with a different (newer) /system,
+ // The vendor and product variants may be used with a different (newer) /system,
// so it shouldn't have any unversioned runtime dependencies, or
// make assumptions about the system that may not be true in the
// future.
//
- // If set to false, this module becomes inaccessible from /vendor modules.
+ // If set to false, this module becomes inaccessible from /vendor or /product
+ // modules.
//
// Default value is true when vndk: {enabled: true} or vendor: true.
//
// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
+ // If PRODUCT_PRODUCT_VNDK_VERSION isn't set, product variant will not be used.
Vendor_available *bool
// whether this module is capable of being loaded with other instance
@@ -283,6 +288,8 @@
isVndk() bool
isVndkSp() bool
isVndkExt() bool
+ inProduct() bool
+ inVendor() bool
inRecovery() bool
shouldCreateSourceAbiDump() bool
selectedStl() string
@@ -417,6 +424,9 @@
hod android.HostOrDeviceSupported
multilib android.Multilib
+ // Allowable SdkMemberTypes of this module type.
+ sdkMemberTypes []android.SdkMemberType
+
// delegates, initialize before calling Init
features []feature
compiler compiler
@@ -680,7 +690,7 @@
}
func (c *Module) VndkVersion() string {
- return c.vndkVersion()
+ return c.Properties.VndkVersion
}
func (c *Module) Init() android.Module {
@@ -752,6 +762,12 @@
return false
}
+// Returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64.
+// "product" and "vendor" variant modules return true for this function.
+// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true",
+// "soc_specific: true" and more vendor installed modules are included here.
+// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "vendor_available: true" or
+// "product_specific: true" modules are included here.
func (c *Module) UseVndk() bool {
return c.Properties.VndkVersion != ""
}
@@ -787,10 +803,6 @@
return false
}
-func (c *Module) vndkVersion() string {
- return c.Properties.VndkVersion
-}
-
func (c *Module) isPgoCompile() bool {
if pgo := c.pgo; pgo != nil {
return pgo.Properties.PgoCompile
@@ -830,12 +842,32 @@
return ""
}
-// Returns true only when this module is configured to have core and vendor
+// Returns true only when this module is configured to have core, product and vendor
// variants.
func (c *Module) HasVendorVariant() bool {
return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
}
+const (
+ // VendorVariationPrefix is the variant prefix used for /vendor code that compiles
+ // against the VNDK.
+ VendorVariationPrefix = "vendor."
+
+ // ProductVariationPrefix is the variant prefix used for /product code that compiles
+ // against the VNDK.
+ ProductVariationPrefix = "product."
+)
+
+// Returns true if the module is "product" variant. Usually these modules are installed in /product
+func (c *Module) inProduct() bool {
+ return c.Properties.ImageVariationPrefix == ProductVariationPrefix
+}
+
+// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
+func (c *Module) inVendor() bool {
+ return c.Properties.ImageVariationPrefix == VendorVariationPrefix
+}
+
func (c *Module) InRecovery() bool {
return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
}
@@ -944,9 +976,14 @@
moduleContextImpl
}
+func (ctx *moduleContext) ProductSpecific() bool {
+ return ctx.ModuleContext.ProductSpecific() ||
+ (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
+}
+
func (ctx *moduleContext) SocSpecific() bool {
return ctx.ModuleContext.SocSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.UseVndk() && !ctx.mod.IsVndk())
+ (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
}
type moduleContextImpl struct {
@@ -980,15 +1017,11 @@
func (ctx *moduleContextImpl) sdkVersion() string {
if ctx.ctx.Device() {
if ctx.useVndk() {
- vndk_ver := ctx.ctx.DeviceConfig().VndkVersion()
- if vndk_ver == "current" {
- platform_vndk_ver := ctx.ctx.DeviceConfig().PlatformVndkVersion()
- if inList(platform_vndk_ver, ctx.ctx.Config().PlatformVersionCombinedCodenames()) {
- return "current"
- }
- return platform_vndk_ver
+ vndkVer := ctx.mod.VndkVersion()
+ if inList(vndkVer, ctx.ctx.Config().PlatformVersionCombinedCodenames()) {
+ return "current"
}
- return vndk_ver
+ return vndkVer
}
return String(ctx.mod.Properties.Sdk_version)
}
@@ -1039,6 +1072,14 @@
return ctx.mod.MustUseVendorVariant()
}
+func (ctx *moduleContextImpl) inProduct() bool {
+ return ctx.mod.inProduct()
+}
+
+func (ctx *moduleContextImpl) inVendor() bool {
+ return ctx.mod.inVendor()
+}
+
func (ctx *moduleContextImpl) inRecovery() bool {
return ctx.mod.InRecovery()
}
@@ -1222,6 +1263,29 @@
return ok && test.isAllTestsVariation()
}
+func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string {
+ // Returns the name suffix for product and vendor variants. If the VNDK version is not
+ // "current", it will append the VNDK version to the name suffix.
+ var vndkVersion string
+ var nameSuffix string
+ if c.inProduct() {
+ vndkVersion = ctx.DeviceConfig().ProductVndkVersion()
+ nameSuffix = productSuffix
+ } else {
+ vndkVersion = ctx.DeviceConfig().VndkVersion()
+ nameSuffix = vendorSuffix
+ }
+ if vndkVersion == "current" {
+ vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
+ }
+ if c.Properties.VndkVersion != vndkVersion {
+ // add version suffix only if the module is using different vndk version than the
+ // version in product or vendor partition.
+ nameSuffix += "." + c.Properties.VndkVersion
+ }
+ return nameSuffix
+}
+
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
// Handle the case of a test module split by `test_per_src` mutator.
//
@@ -1241,21 +1305,17 @@
c.Properties.SubName += nativeBridgeSuffix
}
- if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ _, llndk := c.linker.(*llndkStubDecorator)
+ _, llndkHeader := c.linker.(*llndkHeadersDecorator)
+ if llndk || llndkHeader || (c.UseVndk() && c.HasVendorVariant()) {
+ // .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
+ // added for product variant only when we have vendor and product variants with core
+ // variant. The suffix is not added for vendor-only or product-only module.
+ c.Properties.SubName += c.getNameSuffixWithVndkVersion(actx)
+ } else if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
// .vendor suffix is added for backward compatibility with VNDK snapshot whose names with
// such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
c.Properties.SubName += vendorSuffix
- } else if _, ok := c.linker.(*llndkStubDecorator); ok || (c.UseVndk() && c.HasVendorVariant()) {
- // .vendor.{version} suffix is added only when we will have two variants: core and vendor.
- // The suffix is not added for vendor-only module.
- c.Properties.SubName += vendorSuffix
- vendorVersion := actx.DeviceConfig().VndkVersion()
- if vendorVersion == "current" {
- vendorVersion = actx.DeviceConfig().PlatformVndkVersion()
- }
- if c.Properties.VndkVersion != vendorVersion {
- c.Properties.SubName += "." + c.Properties.VndkVersion
- }
} else if c.InRecovery() && !c.OnlyInRecovery() {
c.Properties.SubName += recoverySuffix
}
@@ -2203,15 +2263,7 @@
} else if c.UseVndk() && bothVendorAndCoreVariantsExist {
// The vendor module in Make will have been renamed to not conflict with the core
// module, so update the dependency name here accordingly.
- ret := libName + vendorSuffix
- vendorVersion := ctx.DeviceConfig().VndkVersion()
- if vendorVersion == "current" {
- vendorVersion = ctx.DeviceConfig().PlatformVndkVersion()
- }
- if c.Properties.VndkVersion != vendorVersion {
- ret += "." + c.Properties.VndkVersion
- }
- return ret
+ return libName + c.getNameSuffixWithVndkVersion(ctx)
} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
return libName + vendorPublicLibrarySuffix
} else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
@@ -2364,6 +2416,9 @@
}
return "native:vndk_private"
}
+ if c.inProduct() {
+ return "native:product"
+ }
return "native:vendor"
} else if c.InRecovery() {
return "native:recovery"
@@ -2408,14 +2463,6 @@
return c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid()
}
-func (c *Module) IDEInfo(dpInfo *android.IdeInfo) {
- outputFiles, err := c.OutputFiles("")
- if err != nil {
- panic(err)
- }
- dpInfo.Srcs = append(dpInfo.Srcs, outputFiles.Strings()...)
-}
-
func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
if c.linker != nil {
if library, ok := c.linker.(*libraryDecorator); ok {
@@ -2489,12 +2536,6 @@
return module
}
-const (
- // VendorVariationPrefix is the variant prefix used for /vendor code that compiles
- // against the VNDK.
- VendorVariationPrefix = "vendor."
-)
-
func squashVendorSrcs(m *Module) {
if lib, ok := m.compiler.(*libraryDecorator); ok {
lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
@@ -2566,49 +2607,65 @@
var recoveryVariantNeeded bool = false
var vendorVariants []string
+ var productVariants []string
platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
- deviceVndkVersion := mctx.DeviceConfig().VndkVersion()
- if deviceVndkVersion == "current" {
- deviceVndkVersion = platformVndkVersion
+ boardVndkVersion := mctx.DeviceConfig().VndkVersion()
+ productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
+ if boardVndkVersion == "current" {
+ boardVndkVersion = platformVndkVersion
+ }
+ if productVndkVersion == "current" {
+ productVndkVersion = platformVndkVersion
}
- if mctx.DeviceConfig().VndkVersion() == "" {
+ if boardVndkVersion == "" {
// If the device isn't compiling against the VNDK, we always
// use the core mode.
coreVariantNeeded = true
} else if _, ok := m.linker.(*llndkStubDecorator); ok {
- // LL-NDK stubs only exist in the vendor variant, since the
- // real libraries will be used in the core variant.
+ // LL-NDK stubs only exist in the vendor and product variants,
+ // since the real libraries will be used in the core variant.
vendorVariants = append(vendorVariants,
platformVndkVersion,
- deviceVndkVersion,
+ boardVndkVersion,
+ )
+ productVariants = append(productVariants,
+ platformVndkVersion,
+ productVndkVersion,
)
} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
// ... and LL-NDK headers as well
vendorVariants = append(vendorVariants,
platformVndkVersion,
- deviceVndkVersion,
+ boardVndkVersion,
+ )
+ productVariants = append(productVariants,
+ platformVndkVersion,
+ productVndkVersion,
)
} else if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
// PRODUCT_EXTRA_VNDK_VERSIONS.
vendorVariants = append(vendorVariants, lib.version())
} else if m.HasVendorVariant() && !vendorSpecific {
- // This will be available in both /system and /vendor
- // or a /system directory that is available to vendor.
+ // This will be available in /system, /vendor and /product
+ // or a /system directory that is available to vendor and product.
coreVariantNeeded = true
vendorVariants = append(vendorVariants, platformVndkVersion)
+ productVariants = append(productVariants, platformVndkVersion)
// VNDK modules must not create BOARD_VNDK_VERSION variant because its
// code is PLATFORM_VNDK_VERSION.
// On the other hand, vendor_available modules which are not VNDK should
// also build BOARD_VNDK_VERSION because it's installed in /vendor.
+ // vendor_available modules are also available to /product.
if !m.IsVndk() {
- vendorVariants = append(vendorVariants, deviceVndkVersion)
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ productVariants = append(productVariants, productVndkVersion)
}
} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
// This will be available in /vendor (or /odm) only
- vendorVariants = append(vendorVariants, deviceVndkVersion)
+ vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
// This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK
@@ -2616,6 +2673,19 @@
coreVariantNeeded = true
}
+ if boardVndkVersion != "" && productVndkVersion != "" {
+ if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
+ // The module has "product_specific: true" that does not create core variant.
+ coreVariantNeeded = false
+ productVariants = append(productVariants, productVndkVersion)
+ }
+ } else {
+ // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
+ // restriction to use system libs.
+ // No product variants defined in this case.
+ productVariants = []string{}
+ }
+
if Bool(m.Properties.Recovery_available) {
recoveryVariantNeeded = true
}
@@ -2626,7 +2696,11 @@
}
for _, variant := range android.FirstUniqueStrings(vendorVariants) {
- m.Properties.VendorVariants = append(m.Properties.VendorVariants, VendorVariationPrefix+variant)
+ m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
+ }
+
+ for _, variant := range android.FirstUniqueStrings(productVariants) {
+ m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
}
m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
@@ -2642,7 +2716,7 @@
}
func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
- return c.Properties.VendorVariants
+ return c.Properties.ExtraVariants
}
func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
@@ -2651,8 +2725,13 @@
m.MakeAsPlatform()
squashRecoverySrcs(m)
} else if strings.HasPrefix(variant, VendorVariationPrefix) {
+ m.Properties.ImageVariationPrefix = VendorVariationPrefix
m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
squashVendorSrcs(m)
+ } else if strings.HasPrefix(variant, ProductVariationPrefix) {
+ m.Properties.ImageVariationPrefix = ProductVariationPrefix
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
+ squashVendorSrcs(m)
}
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 27ff38f..4d02f4f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -82,11 +82,8 @@
return testCcWithConfig(t, config)
}
-func testCcError(t *testing.T, pattern string, bp string) {
+func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
t.Helper()
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := CreateTestContext()
ctx.Register(config)
@@ -106,9 +103,27 @@
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
}
+func testCcError(t *testing.T, pattern string, bp string) {
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ testCcErrorWithConfig(t, pattern, config)
+ return
+}
+
+func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ testCcErrorWithConfig(t, pattern, config)
+ return
+}
+
const (
coreVariant = "android_arm64_armv8-a_shared"
vendorVariant = "android_vendor.VER_arm64_armv8-a_shared"
+ productVariant = "android_product.VER_arm64_armv8-a_shared"
recoveryVariant = "android_recovery_arm64_armv8-a_shared"
)
@@ -280,7 +295,14 @@
func checkVndkLibrariesOutput(t *testing.T, ctx *android.TestContext, module string, expected []string) {
t.Helper()
vndkLibraries := ctx.ModuleForTests(module, "")
- output := insertVndkVersion(module, "VER")
+
+ var output string
+ if module != "vndkcorevariant.libraries.txt" {
+ output = insertVndkVersion(module, "VER")
+ } else {
+ output = module
+ }
+
checkWriteFileOutput(t, vndkLibraries.Output(output), expected)
}
@@ -1445,6 +1467,160 @@
`)
}
+func TestEnforceProductVndkVersion(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libllndk",
+ }
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ cc_library {
+ name: "libvndk_sp",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ nocrt: true,
+ }
+ cc_library {
+ name: "libva",
+ vendor_available: true,
+ nocrt: true,
+ }
+ cc_library {
+ name: "libproduct_va",
+ product_specific: true,
+ vendor_available: true,
+ nocrt: true,
+ }
+ cc_library {
+ name: "libprod",
+ product_specific: true,
+ shared_libs: [
+ "libllndk",
+ "libvndk",
+ "libvndk_sp",
+ "libva",
+ "libproduct_va",
+ ],
+ nocrt: true,
+ }
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ shared_libs: [
+ "libllndk",
+ "libvndk",
+ "libvndk_sp",
+ "libva",
+ "libproduct_va",
+ ],
+ nocrt: true,
+ }
+ `
+
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+ ctx := testCcWithConfig(t, config)
+
+ checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
+ checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
+}
+
+func TestEnforceProductVndkVersionErrors(t *testing.T) {
+ testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
+ cc_library {
+ name: "libprod",
+ product_specific: true,
+ shared_libs: [
+ "libvendor",
+ ],
+ nocrt: true,
+ }
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ nocrt: true,
+ }
+ `)
+ testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
+ cc_library {
+ name: "libprod",
+ product_specific: true,
+ shared_libs: [
+ "libsystem",
+ ],
+ nocrt: true,
+ }
+ cc_library {
+ name: "libsystem",
+ nocrt: true,
+ }
+ `)
+ testCcErrorProductVndk(t, "Vendor module that is not VNDK should not link to \".*\" which is marked as `vendor_available: false`", `
+ cc_library {
+ name: "libprod",
+ product_specific: true,
+ shared_libs: [
+ "libvndk_private",
+ ],
+ nocrt: true,
+ }
+ cc_library {
+ name: "libvndk_private",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ `)
+ testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
+ cc_library {
+ name: "libprod",
+ product_specific: true,
+ shared_libs: [
+ "libsystem_ext",
+ ],
+ nocrt: true,
+ }
+ cc_library {
+ name: "libsystem_ext",
+ system_ext_specific: true,
+ nocrt: true,
+ }
+ `)
+ testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:", `
+ cc_library {
+ name: "libsystem",
+ shared_libs: [
+ "libproduct_va",
+ ],
+ nocrt: true,
+ }
+ cc_library {
+ name: "libproduct_va",
+ product_specific: true,
+ vendor_available: true,
+ nocrt: true,
+ }
+ `)
+}
+
func TestMakeLinkType(t *testing.T) {
bp := `
cc_library {
diff --git a/cc/ccdeps.go b/cc/ccdeps.go
new file mode 100644
index 0000000..9b89110
--- /dev/null
+++ b/cc/ccdeps.go
@@ -0,0 +1,252 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "path"
+ "sort"
+ "strings"
+
+ "android/soong/android"
+)
+
+// This singleton collects cc modules' source and flags into to a json file.
+// It does so for generating CMakeLists.txt project files needed data when
+// either make, mm, mma, mmm or mmma is called.
+// The info file is generated in $OUT/module_bp_cc_depend.json.
+
+func init() {
+ android.RegisterSingletonType("ccdeps_generator", ccDepsGeneratorSingleton)
+}
+
+func ccDepsGeneratorSingleton() android.Singleton {
+ return &ccdepsGeneratorSingleton{}
+}
+
+type ccdepsGeneratorSingleton struct {
+}
+
+const (
+ // Environment variables used to control the behavior of this singleton.
+ envVariableCollectCCDeps = "SOONG_COLLECT_CC_DEPS"
+ ccdepsJsonFileName = "module_bp_cc_deps.json"
+ cClang = "clang"
+ cppClang = "clang++"
+)
+
+type ccIdeInfo struct {
+ Path []string `json:"path,omitempty"`
+ Srcs []string `json:"srcs,omitempty"`
+ Global_Common_Flags ccParameters `json:"global_common_flags,omitempty"`
+ Local_Common_Flags ccParameters `json:"local_common_flags,omitempty"`
+ Global_C_flags ccParameters `json:"global_c_flags,omitempty"`
+ Local_C_flags ccParameters `json:"local_c_flags,omitempty"`
+ Global_C_only_flags ccParameters `json:"global_c_only_flags,omitempty"`
+ Local_C_only_flags ccParameters `json:"local_c_only_flags,omitempty"`
+ Global_Cpp_flags ccParameters `json:"global_cpp_flags,omitempty"`
+ Local_Cpp_flags ccParameters `json:"local_cpp_flags,omitempty"`
+ System_include_flags ccParameters `json:"system_include_flags,omitempty"`
+ Module_name string `json:"module_name,omitempty"`
+}
+
+type ccParameters struct {
+ HeaderSearchPath []string `json:"header_search_path,omitempty"`
+ SystemHeaderSearchPath []string `json:"system_search_path,omitempty"`
+ FlagParameters []string `json:"flag,omitempty"`
+ SysRoot string `json:"system_root,omitempty"`
+ RelativeFilePathFlags map[string]string `json:"relative_file_path,omitempty"`
+}
+
+type ccMapIdeInfos map[string]ccIdeInfo
+
+type ccDeps struct {
+ C_clang string `json:"clang,omitempty"`
+ Cpp_clang string `json:"clang++,omitempty"`
+ Modules ccMapIdeInfos `json:"modules,omitempty"`
+}
+
+func (c *ccdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ if !ctx.Config().IsEnvTrue(envVariableCollectCCDeps) {
+ return
+ }
+
+ moduleDeps := ccDeps{}
+ moduleInfos := map[string]ccIdeInfo{}
+
+ // Track which projects have already had CMakeLists.txt generated to keep the first
+ // variant for each project.
+ seenProjects := map[string]bool{}
+
+ pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
+ moduleDeps.C_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cClang)
+ moduleDeps.Cpp_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cppClang)
+
+ ctx.VisitAllModules(func(module android.Module) {
+ if ccModule, ok := module.(*Module); ok {
+ if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
+ generateCLionProjectData(ctx, compiledModule, ccModule, seenProjects, moduleInfos)
+ }
+ }
+ })
+
+ moduleDeps.Modules = moduleInfos
+
+ ccfpath := android.PathForOutput(ctx, ccdepsJsonFileName).String()
+ err := createJsonFile(moduleDeps, ccfpath)
+ if err != nil {
+ ctx.Errorf(err.Error())
+ }
+}
+
+func parseCompilerCCParameters(ctx android.SingletonContext, params []string) ccParameters {
+ compilerParams := ccParameters{}
+
+ cparams := []string{}
+ for _, param := range params {
+ param, _ = evalVariable(ctx, param)
+ cparams = append(cparams, param)
+ }
+
+ // Soong does not guarantee that each flag will be in an individual string. e.g: The
+ // input received could be:
+ // params = {"-isystem", "path/to/system"}
+ // or it could be
+ // params = {"-isystem path/to/system"}
+ // To normalize the input, we split all strings with the "space" character and consolidate
+ // all tokens into a flattened parameters list
+ cparams = normalizeParameters(cparams)
+
+ for i := 0; i < len(cparams); i++ {
+ param := cparams[i]
+ if param == "" {
+ continue
+ }
+
+ switch categorizeParameter(param) {
+ case headerSearchPath:
+ compilerParams.HeaderSearchPath =
+ append(compilerParams.HeaderSearchPath, strings.TrimPrefix(param, "-I"))
+ case systemHeaderSearchPath:
+ if i < len(params)-1 {
+ compilerParams.SystemHeaderSearchPath = append(compilerParams.SystemHeaderSearchPath, cparams[i+1])
+ }
+ i = i + 1
+ case flag:
+ c := cleanupParameter(param)
+ compilerParams.FlagParameters = append(compilerParams.FlagParameters, c)
+ case systemRoot:
+ if i < len(cparams)-1 {
+ compilerParams.SysRoot = cparams[i+1]
+ }
+ i = i + 1
+ case relativeFilePathFlag:
+ flagComponents := strings.Split(param, "=")
+ if len(flagComponents) == 2 {
+ if compilerParams.RelativeFilePathFlags == nil {
+ compilerParams.RelativeFilePathFlags = map[string]string{}
+ }
+ compilerParams.RelativeFilePathFlags[flagComponents[0]] = flagComponents[1]
+ }
+ }
+ }
+ return compilerParams
+}
+
+func generateCLionProjectData(ctx android.SingletonContext, compiledModule CompiledInterface,
+ ccModule *Module, seenProjects map[string]bool, moduleInfos map[string]ccIdeInfo) {
+ srcs := compiledModule.Srcs()
+ if len(srcs) == 0 {
+ return
+ }
+
+ // Only keep the DeviceArch variant module.
+ if ctx.DeviceConfig().DeviceArch() != ccModule.ModuleBase.Arch().ArchType.Name {
+ return
+ }
+
+ clionProjectLocation := getCMakeListsForModule(ccModule, ctx)
+ if seenProjects[clionProjectLocation] {
+ return
+ }
+
+ seenProjects[clionProjectLocation] = true
+
+ name := ccModule.ModuleBase.Name()
+ dpInfo := moduleInfos[name]
+
+ dpInfo.Path = append(dpInfo.Path, path.Dir(ctx.BlueprintFile(ccModule)))
+ dpInfo.Srcs = append(dpInfo.Srcs, srcs.Strings()...)
+ dpInfo.Path = android.FirstUniqueStrings(dpInfo.Path)
+ dpInfo.Srcs = android.FirstUniqueStrings(dpInfo.Srcs)
+
+ dpInfo.Global_Common_Flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CommonFlags)
+ dpInfo.Local_Common_Flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CommonFlags)
+ dpInfo.Global_C_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CFlags)
+ dpInfo.Local_C_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CFlags)
+ dpInfo.Global_C_only_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.ConlyFlags)
+ dpInfo.Local_C_only_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.ConlyFlags)
+ dpInfo.Global_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CppFlags)
+ dpInfo.Local_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CppFlags)
+ dpInfo.System_include_flags = parseCompilerCCParameters(ctx, ccModule.flags.SystemIncludeFlags)
+
+ dpInfo.Module_name = name
+
+ moduleInfos[name] = dpInfo
+}
+
+type Deal struct {
+ Name string
+ ideInfo ccIdeInfo
+}
+
+type Deals []Deal
+
+// Ensure it satisfies sort.Interface
+func (d Deals) Len() int { return len(d) }
+func (d Deals) Less(i, j int) bool { return d[i].Name < d[j].Name }
+func (d Deals) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
+
+func sortMap(moduleInfos map[string]ccIdeInfo) map[string]ccIdeInfo {
+ var deals Deals
+ for k, v := range moduleInfos {
+ deals = append(deals, Deal{k, v})
+ }
+
+ sort.Sort(deals)
+
+ m := map[string]ccIdeInfo{}
+ for _, d := range deals {
+ m[d.Name] = d.ideInfo
+ }
+ return m
+}
+
+func createJsonFile(moduleDeps ccDeps, ccfpath string) error {
+ file, err := os.Create(ccfpath)
+ if err != nil {
+ return fmt.Errorf("Failed to create file: %s, relative: %v", ccdepsJsonFileName, err)
+ }
+ defer file.Close()
+ moduleDeps.Modules = sortMap(moduleDeps.Modules)
+ buf, err := json.MarshalIndent(moduleDeps, "", "\t")
+ if err != nil {
+ return fmt.Errorf("Write file failed: %s, relative: %v", ccdepsJsonFileName, err)
+ }
+ fmt.Fprintf(file, string(buf))
+ return nil
+}
diff --git a/cc/genrule.go b/cc/genrule.go
index b9765a4..548d5f2 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -55,6 +55,10 @@
return true
}
+ if ctx.DeviceConfig().ProductVndkVersion() != "" && ctx.ProductSpecific() {
+ return false
+ }
+
return Bool(g.Vendor_available) || !(ctx.SocSpecific() || ctx.DeviceSpecific())
}
@@ -67,16 +71,26 @@
return nil
}
+ var variants []string
if Bool(g.Vendor_available) || ctx.SocSpecific() || ctx.DeviceSpecific() {
- var variants []string
variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
if vndkVersion := ctx.DeviceConfig().VndkVersion(); vndkVersion != "current" {
variants = append(variants, VendorVariationPrefix+vndkVersion)
}
+ }
+
+ if ctx.DeviceConfig().ProductVndkVersion() == "" {
return variants
}
- return nil
+ if Bool(g.Vendor_available) || ctx.ProductSpecific() {
+ variants = append(variants, ProductVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
+ if vndkVersion := ctx.DeviceConfig().ProductVndkVersion(); vndkVersion != "current" {
+ variants = append(variants, ProductVariationPrefix+vndkVersion)
+ }
+ }
+
+ return variants
}
func (g *GenruleExtraProperties) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
diff --git a/cc/installer.go b/cc/installer.go
index 9fdc88a..2f55ac5 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -72,7 +72,11 @@
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
if installer.location == InstallInData && ctx.useVndk() {
- dir = filepath.Join(dir, "vendor")
+ if ctx.inProduct() {
+ dir = filepath.Join(dir, "product")
+ } else {
+ dir = filepath.Join(dir, "vendor")
+ }
}
return android.PathForModuleInstall(ctx, dir, installer.subDir,
installer.relativeInstallPath(), installer.relative)
diff --git a/cc/library.go b/cc/library.go
index 04130c4..ae95bc5 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -174,12 +174,16 @@
}
func init() {
- android.RegisterModuleType("cc_library_static", LibraryStaticFactory)
- android.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
- android.RegisterModuleType("cc_library", LibraryFactory)
- android.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory)
- android.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory)
- android.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
+ RegisterLibraryBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterLibraryBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cc_library_static", LibraryStaticFactory)
+ ctx.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
+ ctx.RegisterModuleType("cc_library", LibraryFactory)
+ ctx.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory)
+ ctx.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory)
+ ctx.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
}
// cc_library creates both static and/or shared libraries for a device and/or
@@ -188,6 +192,11 @@
// host.
func LibraryFactory() android.Module {
module, _ := NewLibrary(android.HostAndDeviceSupported)
+ // Can be used as both a static and a shared library.
+ module.sdkMemberTypes = []android.SdkMemberType{
+ sharedLibrarySdkMemberType,
+ staticLibrarySdkMemberType,
+ }
return module.Init()
}
@@ -195,6 +204,7 @@
func LibraryStaticFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
+ module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
return module.Init()
}
@@ -202,6 +212,7 @@
func LibrarySharedFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyShared()
+ module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
return module.Init()
}
@@ -210,6 +221,7 @@
func LibraryHostStaticFactory() android.Module {
module, library := NewLibrary(android.HostSupported)
library.BuildOnlyStatic()
+ module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
return module.Init()
}
@@ -217,6 +229,7 @@
func LibraryHostSharedFactory() android.Module {
module, library := NewLibrary(android.HostSupported)
library.BuildOnlyShared()
+ module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
return module.Init()
}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 9319070..fd5a4da 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -24,23 +24,28 @@
// This file contains support for using cc library modules within an sdk.
+var sharedLibrarySdkMemberType = &librarySdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "native_shared_libs",
+ SupportsSdk: true,
+ },
+ prebuiltModuleType: "cc_prebuilt_library_shared",
+ linkTypes: []string{"shared"},
+}
+
+var staticLibrarySdkMemberType = &librarySdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "native_static_libs",
+ SupportsSdk: true,
+ },
+ prebuiltModuleType: "cc_prebuilt_library_static",
+ linkTypes: []string{"static"},
+}
+
func init() {
// Register sdk member types.
- android.RegisterSdkMemberType(&librarySdkMemberType{
- SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "native_shared_libs",
- },
- prebuiltModuleType: "cc_prebuilt_library_shared",
- linkTypes: []string{"shared"},
- })
-
- android.RegisterSdkMemberType(&librarySdkMemberType{
- SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "native_static_libs",
- },
- prebuiltModuleType: "cc_prebuilt_library_static",
- linkTypes: []string{"static"},
- })
+ android.RegisterSdkMemberType(sharedLibrarySdkMemberType)
+ android.RegisterSdkMemberType(staticLibrarySdkMemberType)
}
type librarySdkMemberType struct {
@@ -72,8 +77,16 @@
}
func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
- _, ok := module.(*Module)
- return ok
+ // Check the module to see if it can be used with this module type.
+ if m, ok := module.(*Module); ok {
+ for _, allowableMemberType := range m.sdkMemberTypes {
+ if allowableMemberType == mt {
+ return true
+ }
+ }
+ }
+
+ return false
}
// copy exported header files and stub *.so files
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index f3ee5c1..3dee692 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -76,17 +76,12 @@
}
func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
- vndk_ver := ctx.Module().(*Module).Properties.VndkVersion
- if vndk_ver == "current" {
- platform_vndk_ver := ctx.DeviceConfig().PlatformVndkVersion()
- if !inList(platform_vndk_ver, ctx.Config().PlatformVersionCombinedCodenames()) {
- vndk_ver = platform_vndk_ver
- }
- } else if vndk_ver == "" {
- // For non-enforcing devices, use "current"
- vndk_ver = "current"
+ vndkVer := ctx.Module().(*Module).VndkVersion()
+ if !inList(vndkVer, ctx.Config().PlatformVersionCombinedCodenames()) || vndkVer == "" {
+ // For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
+ vndkVer = "current"
}
- objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndk_ver, "--llndk")
+ objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
stub.versionScriptPath = versionScript
return objs
}
diff --git a/cc/testing.go b/cc/testing.go
index de4f1ec..bc31077 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -20,14 +20,14 @@
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
RegisterPrebuiltBuildComponents(ctx)
- ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
- ctx.RegisterModuleType("cc_library", LibraryFactory)
- ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
- ctx.RegisterModuleType("cc_object", ObjectFactory)
-
android.RegisterPrebuiltMutators(ctx)
RegisterCCBuildComponents(ctx)
+ RegisterLibraryBuildComponents(ctx)
+
+ ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
+ ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
+ ctx.RegisterModuleType("cc_object", ObjectFactory)
}
func GatherRequiredDepsForTest(os android.OsType) string {
@@ -308,9 +308,6 @@
ctx.RegisterModuleType("cc_binary", BinaryFactory)
ctx.RegisterModuleType("cc_binary_host", binaryHostFactory)
ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
- ctx.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
- ctx.RegisterModuleType("cc_library_static", LibraryStaticFactory)
- ctx.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
ctx.RegisterModuleType("cc_test", TestFactory)
ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
diff --git a/cc/vndk.go b/cc/vndk.go
index f531af3..872a473 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -42,7 +42,6 @@
vndkCoreLibrariesTxt,
vndkSpLibrariesTxt,
vndkPrivateLibrariesTxt,
- vndkUsingCoreVariantLibrariesTxt,
}
}
// Snapshot vndks have their own *.libraries.VER.txt files.
@@ -132,16 +131,16 @@
return
}
if !vndk.isVndk() {
- // Non-VNDK modules (those installed to /vendor) can't depend on modules marked with
- // vendor_available: false.
+ // Non-VNDK modules (those installed to /vendor, /product, or /system/product) can't depend
+ // on modules marked with vendor_available: false.
violation := false
if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) {
violation = true
} else {
if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) {
// Vendor_available == nil && !Bool(Vendor_available) should be okay since
- // it means a vendor-only library which is a valid dependency for non-VNDK
- // modules.
+ // it means a vendor-only, or product-only library which is a valid dependency
+ // for non-VNDK modules.
violation = true
}
}
@@ -227,7 +226,7 @@
vndkSpLibrariesKey = android.NewOnceKey("vndkSpLibrarires")
llndkLibrariesKey = android.NewOnceKey("llndkLibrarires")
vndkPrivateLibrariesKey = android.NewOnceKey("vndkPrivateLibrarires")
- vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibrarires")
+ vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibraries")
vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey")
vndkLibrariesLock sync.Mutex
@@ -350,7 +349,7 @@
}
if lib, ok := m.linker.(libraryInterface); ok {
- useCoreVariant := m.vndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
+ useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
return lib.shared() && m.UseVndk() && m.IsVndk() && !m.isVndkExt() && !useCoreVariant
}
@@ -445,7 +444,13 @@
return
}
- filename := insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
+ var filename string
+ if txt.Name() != vndkUsingCoreVariantLibrariesTxt {
+ filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
+ } else {
+ filename = txt.Name()
+ }
+
txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
ctx.Build(pctx, android.BuildParams{
Rule: android.WriteFile,
@@ -665,14 +670,14 @@
if m.Target().NativeBridge == android.NativeBridgeEnabled {
return nil, "", false
}
- if !m.UseVndk() || !m.IsForPlatform() || !m.installable() {
+ if !m.UseVndk() || !m.IsForPlatform() || !m.installable() || !m.inVendor() {
return nil, "", false
}
l, ok := m.linker.(vndkSnapshotLibraryInterface)
if !ok || !l.shared() {
return nil, "", false
}
- if m.vndkVersion() == ctx.DeviceConfig().PlatformVndkVersion() && m.IsVndk() && !m.isVndkExt() {
+ if m.VndkVersion() == ctx.DeviceConfig().PlatformVndkVersion() && m.IsVndk() && !m.isVndkExt() {
if m.isVndkSp() {
return l, "vndk-sp", true
} else {
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 4771206..7329aee 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -37,18 +37,7 @@
"android/soong/zip"
)
-// We default to number of cpus / 4, which seems to be the sweet spot for my
-// system. I suspect this is mostly due to memory or disk bandwidth though, and
-// may depend on the size ofthe source tree, so this probably isn't a great
-// default.
-func detectNumJobs() int {
- if runtime.NumCPU() < 4 {
- return 1
- }
- return runtime.NumCPU() / 4
-}
-
-var numJobs = flag.Int("j", detectNumJobs(), "number of parallel kati jobs")
+var numJobs = flag.Int("j", 0, "number of parallel jobs [0=autodetect]")
var keepArtifacts = flag.Bool("keep", false, "keep archives of artifacts")
var incremental = flag.Bool("incremental", false, "run in incremental mode (saving intermediates)")
@@ -233,6 +222,21 @@
trace.SetOutput(filepath.Join(config.OutDir(), "build.trace"))
}
+ var jobs = *numJobs
+ if jobs < 1 {
+ jobs = runtime.NumCPU() / 4
+
+ ramGb := int(config.TotalRAM() / 1024 / 1024 / 1024)
+ if ramJobs := ramGb / 20; ramGb > 0 && jobs > ramJobs {
+ jobs = ramJobs
+ }
+
+ if jobs < 1 {
+ jobs = 1
+ }
+ }
+ log.Verbosef("Using %d parallel jobs", jobs)
+
setMaxFiles(log)
finder := build.NewSourceFinder(buildCtx, config)
@@ -318,7 +322,7 @@
}()
var wg sync.WaitGroup
- for i := 0; i < *numJobs; i++ {
+ for i := 0; i < jobs; i++ {
wg.Add(1)
go func() {
defer wg.Done()
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 3b7f772..f62f5f9 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -34,6 +34,9 @@
android.RegisterSdkMemberType(&droidStubsSdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "stubs_sources",
+ // stubs_sources can be used with sdk to provide the source stubs for APIs provided by
+ // the APEX.
+ SupportsSdk: true,
},
})
}
@@ -1948,12 +1951,42 @@
properties PrebuiltStubsSourcesProperties
- srcs android.Paths
+ // The source directories containing stubs source files.
+ srcDirs android.Paths
stubsSrcJar android.ModuleOutPath
}
+func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return android.Paths{p.stubsSrcJar}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.srcs = android.PathsForModuleSrc(ctx, p.properties.Srcs)
+ p.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
+
+ p.srcDirs = android.PathsForModuleSrc(ctx, p.properties.Srcs)
+
+ rule := android.NewRuleBuilder()
+ command := rule.Command().
+ BuiltTool(ctx, "soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", p.stubsSrcJar)
+
+ for _, d := range p.srcDirs {
+ dir := d.String()
+ command.
+ FlagWithArg("-C ", dir).
+ FlagWithInput("-D ", d)
+ }
+
+ rule.Restat()
+
+ rule.Build(pctx, ctx, "zip src", "Create srcjar from prebuilt source")
}
func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
@@ -1964,10 +1997,6 @@
return p.prebuilt.Name(p.ModuleBase.Name())
}
-func (p *PrebuiltStubsSources) Srcs() android.Paths {
- return append(android.Paths{}, p.srcs...)
-}
-
// prebuilt_stubs_sources imports a set of java source files as if they were
// generated by droidstubs.
//
diff --git a/java/java.go b/java/java.go
index d0bf9d7..a48b5a3 100644
--- a/java/java.go
+++ b/java/java.go
@@ -41,6 +41,7 @@
librarySdkMemberType{
android.SdkMemberTypeBase{
PropertyName: "java_header_libs",
+ SupportsSdk: true,
},
},
})
@@ -52,6 +53,12 @@
},
},
})
+
+ android.RegisterSdkMemberType(&testSdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "java_tests",
+ },
+ })
}
func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
@@ -65,6 +72,7 @@
ctx.RegisterModuleType("java_test", TestFactory)
ctx.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
ctx.RegisterModuleType("java_test_host", TestHostFactory)
+ ctx.RegisterModuleType("java_test_import", JavaTestImportFactory)
ctx.RegisterModuleType("java_import", ImportFactory)
ctx.RegisterModuleType("java_import_host", ImportFactoryHost)
ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
@@ -1764,14 +1772,19 @@
}
const (
- aidlIncludeDir = "aidl"
- javaDir = "java"
- jarFileSuffix = ".jar"
+ aidlIncludeDir = "aidl"
+ javaDir = "java"
+ jarFileSuffix = ".jar"
+ testConfigSuffix = "-AndroidTest.xml"
)
// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
-func (j *Library) sdkSnapshotFilePathForJar() string {
- return filepath.Join(javaDir, j.Name()+jarFileSuffix)
+func sdkSnapshotFilePathForJar(member android.SdkMember) string {
+ return sdkSnapshotFilePathForMember(member, jarFileSuffix)
+}
+
+func sdkSnapshotFilePathForMember(member android.SdkMember, suffix string) string {
+ return filepath.Join(javaDir, member.Name()+suffix)
}
type librarySdkMemberType struct {
@@ -1804,7 +1817,7 @@
j := variant.(*Library)
exportedJar := jarToExportGetter(j)
- snapshotRelativeJavaLibPath := j.sdkSnapshotFilePathForJar()
+ snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member)
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
for _, dir := range j.AidlIncludeDirs() {
@@ -1931,6 +1944,16 @@
Test_suites []string `android:"arch_variant"`
}
+type prebuiltTestProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+
+ // the name of the test configuration (for example "AndroidTest.xml") that should be
+ // installed with the module.
+ Test_config *string `android:"path,arch_variant"`
+}
+
type Test struct {
Library
@@ -1946,6 +1969,14 @@
testHelperLibraryProperties testHelperLibraryProperties
}
+type JavaTestImport struct {
+ Import
+
+ prebuiltTestProperties prebuiltTestProperties
+
+ testConfig android.Path
+}
+
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
j.testProperties.Test_suites, j.testProperties.Auto_gen_config)
@@ -1958,6 +1989,53 @@
j.Library.GenerateAndroidBuildActions(ctx)
}
+func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
+ j.prebuiltTestProperties.Test_suites, nil)
+
+ j.Import.GenerateAndroidBuildActions(ctx)
+}
+
+type testSdkMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (mt *testSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+ mctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (mt *testSdkMemberType) IsInstance(module android.Module) bool {
+ _, ok := module.(*Test)
+ return ok
+}
+
+func (mt *testSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+ variants := member.Variants()
+ if len(variants) != 1 {
+ sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
+ for _, variant := range variants {
+ sdkModuleContext.ModuleErrorf(" %q", variant)
+ }
+ }
+ variant := variants[0]
+ j := variant.(*Test)
+
+ implementationJars := j.ImplementationJars()
+ if len(implementationJars) != 1 {
+ panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
+ }
+
+ snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member)
+ builder.CopyToSnapshot(implementationJars[0], snapshotRelativeJavaLibPath)
+
+ snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(member, testConfigSuffix)
+ builder.CopyToSnapshot(j.testConfig, snapshotRelativeTestConfigPath)
+
+ module := builder.AddPrebuiltModule(member, "java_test_import")
+ module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
+ module.AddProperty("test_config", snapshotRelativeTestConfigPath)
+}
+
// java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
//
@@ -2001,6 +2079,30 @@
return module
}
+// java_test_import imports one or more `.jar` files into the build graph as if they were built by a java_test module
+// and makes sure that it is added to the appropriate test suite.
+//
+// By default, a java_test_import has a single variant that expects a `.jar` file containing `.class` files that were
+// compiled against an Android classpath.
+//
+// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
+// for host modules.
+func JavaTestImportFactory() android.Module {
+ module := &JavaTestImport{}
+
+ module.AddProperties(
+ &module.Import.properties,
+ &module.prebuiltTestProperties)
+
+ module.Import.properties.Installable = proptools.BoolPtr(true)
+
+ android.InitPrebuiltModule(module, &module.properties.Jars)
+ android.InitApexModule(module)
+ android.InitSdkAwareModule(module)
+ InitJavaModule(module, android.HostAndDeviceSupported)
+ return module
+}
+
// java_test_host builds a and links sources into a `.jar` file for the host, and creates an `AndroidTest.xml` file to
// allow running the test with `atest` or a `TEST_MAPPING` file.
//
diff --git a/java/java_test.go b/java/java_test.go
index 096cdb9..30a8ca6 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -484,28 +484,31 @@
prebuilt_stubs_sources {
name: "stubs-source",
- srcs: ["stubs/sources/**/*.java"],
+ srcs: ["stubs/sources"],
+ }
+
+ java_test_import {
+ name: "test",
+ jars: ["a.jar"],
+ test_suites: ["cts"],
+ test_config: "AndroidTest.xml",
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ fooModule := ctx.ModuleForTests("foo", "android_common")
+ javac := fooModule.Rule("javac")
combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
barJar := ctx.ModuleForTests("bar", "android_common").Rule("combineJar").Output
bazJar := ctx.ModuleForTests("baz", "android_common").Rule("combineJar").Output
sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
- inputs := []string{}
- for _, p := range javac.BuildParams.Inputs {
- inputs = append(inputs, p.String())
- }
+ fooLibrary := fooModule.Module().(*Library)
+ assertDeepEquals(t, "foo java sources incorrect",
+ []string{"a.java"}, fooLibrary.compiledJavaSrcs.Strings())
- expected := []string{
- "a.java",
- "stubs/sources/foo/Foo.java",
- }
- if !reflect.DeepEqual(expected, inputs) {
- t.Errorf("foo inputs incorrect: expected %q, found %q", expected, inputs)
- }
+ assertDeepEquals(t, "foo java source jars incorrect",
+ []string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"},
+ android.NormalizePathsForTesting(fooLibrary.compiledSrcJars))
if !strings.Contains(javac.Args["classpath"], barJar.String()) {
t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
@@ -522,6 +525,12 @@
ctx.ModuleForTests("qux", "android_common").Rule("Cp")
}
+func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("%s: expected %q, found %q", message, expected, actual)
+ }
+}
+
func TestDefaults(t *testing.T) {
ctx, _ := testJava(t, `
java_defaults {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index def2753..4492e3f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -16,7 +16,6 @@
import (
"android/soong/android"
- "android/soong/genrule"
"fmt"
"io"
"path"
@@ -25,7 +24,6 @@
"strings"
"sync"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -35,32 +33,26 @@
sdkTestApiSuffix = ".test"
sdkDocsSuffix = ".docs"
sdkXmlFileSuffix = ".xml"
- permissionTemplate = `<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<permissions>
- <library name="%s" file="%s"/>
-</permissions>
-`
+ permissionsTemplate = `<?xml version="1.0" encoding="utf-8"?>\n` +
+ `<!-- Copyright (C) 2018 The Android Open Source Project\n` +
+ `\n` +
+ ` Licensed under the Apache License, Version 2.0 (the "License");\n` +
+ ` you may not use this file except in compliance with the License.\n` +
+ ` You may obtain a copy of the License at\n` +
+ `\n` +
+ ` http://www.apache.org/licenses/LICENSE-2.0\n` +
+ `\n` +
+ ` Unless required by applicable law or agreed to in writing, software\n` +
+ ` distributed under the License is distributed on an "AS IS" BASIS,\n` +
+ ` WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n` +
+ ` See the License for the specific language governing permissions and\n` +
+ ` limitations under the License.\n` +
+ `-->\n` +
+ `<permissions>\n` +
+ ` <library name="%s" file="%s"/>\n` +
+ `</permissions>\n`
)
-type stubsLibraryDependencyTag struct {
- blueprint.BaseDependencyTag
- name string
-}
-
var (
publicApiStubsTag = dependencyTag{name: "public"}
systemApiStubsTag = dependencyTag{name: "system"}
@@ -105,12 +97,22 @@
// List of Java libraries that will be in the classpath when building stubs
Stub_only_libs []string `android:"arch_variant"`
- // list of package names that will be documented and publicized as API
+ // list of package names that will be documented and publicized as API.
+ // This allows the API to be restricted to a subset of the source files provided.
+ // If this is unspecified then all the source files will be treated as being part
+ // of the API.
Api_packages []string
// list of package names that must be hidden from the API
Hidden_api_packages []string
+ // the relative path to the directory containing the api specification files.
+ // Defaults to "api".
+ Api_dir *string
+
+ // If set to true there is no runtime library.
+ Api_only *bool
+
// local files that are used within user customized droiddoc options.
Droiddoc_option_files []string
@@ -133,6 +135,9 @@
// don't create dist rules.
No_dist *bool `blueprint:"mutated"`
+ // indicates whether system and test apis should be managed.
+ Has_system_and_test_apis bool `blueprint:"mutated"`
+
// TODO: determines whether to create HTML doc or not
//Html_doc *bool
}
@@ -154,7 +159,7 @@
systemApiFilePath android.Path
testApiFilePath android.Path
- permissionFile android.Path
+ permissionsFile android.Path
}
var _ Dependency = (*SdkLibrary)(nil)
@@ -168,8 +173,7 @@
}
ctx.AddVariationDependencies(nil, publicApiFileTag, module.docsName(apiScopePublic))
- sdkDep := decodeSdkDep(ctx, sdkContext(&module.Library))
- if sdkDep.hasStandardLibs() {
+ if module.sdkLibraryProperties.Has_system_and_test_apis {
if useBuiltStubs {
ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem))
ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest))
@@ -182,12 +186,13 @@
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- module.Library.GenerateAndroidBuildActions(ctx)
-
- if module.ApexName() != "" {
- module.buildPermissionFile(ctx)
+ // Don't build an implementation library if this is api only.
+ if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ module.Library.GenerateAndroidBuildActions(ctx)
}
+ module.buildPermissionsFile(ctx)
+
// Record the paths to the header jars of the library (stubs and impl).
// When this java_sdk_library is dependened from others via "libs" property,
// the recorded paths will be returned depending on the link type of the caller.
@@ -223,22 +228,34 @@
})
}
-func (module *SdkLibrary) buildPermissionFile(ctx android.ModuleContext) {
- xmlContent := strings.ReplaceAll(fmt.Sprintf(permissionTemplate, module.BaseModuleName(), module.implPath()), "\n", "\\n")
- permissionFile := android.PathForModuleOut(ctx, module.xmlFileName())
+func (module *SdkLibrary) buildPermissionsFile(ctx android.ModuleContext) {
+ xmlContent := fmt.Sprintf(permissionsTemplate, module.BaseModuleName(), module.implPath())
+ permissionsFile := android.PathForModuleOut(ctx, module.xmlFileName())
- rule := android.NewRuleBuilder()
- rule.Command().Text("echo -e ").Text(proptools.ShellEscape(xmlContent)).Text(">").Output(permissionFile)
- rule.Build(pctx, ctx, "gen_permission_xml", "Generate permission")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Output: permissionsFile,
+ Description: "Generating " + module.BaseModuleName() + " permissions",
+ Args: map[string]string{
+ "content": xmlContent,
+ },
+ })
- module.permissionFile = permissionFile
+ module.permissionsFile = permissionsFile
}
-func (module *SdkLibrary) PermissionFile() android.Path {
- return module.permissionFile
+func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case ".xml":
+ return android.Paths{module.permissionsFile}, nil
+ }
+ return module.Library.OutputFiles(tag)
}
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+ if proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ return nil
+ }
entriesList := module.Library.AndroidMkEntries()
entries := &entriesList[0]
entries.Required = append(entries.Required, module.xmlFileName())
@@ -357,7 +374,7 @@
// SDK version that the stubs library is built against. Note that this is always
// *current. Older stubs library built with a numberd SDK version is created from
// the prebuilt jar.
-func (module *SdkLibrary) sdkVersion(apiScope apiScope) string {
+func (module *SdkLibrary) sdkVersionForScope(apiScope apiScope) string {
switch apiScope {
case apiScopePublic:
return "current"
@@ -370,6 +387,18 @@
}
}
+// Get the sdk version for use when compiling the stubs library.
+func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.BaseModuleContext, apiScope apiScope) string {
+ sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ if sdkDep.hasStandardLibs() {
+ // If building against a standard sdk then use the sdk version appropriate for the scope.
+ return module.sdkVersionForScope(apiScope)
+ } else {
+ // Otherwise, use no system module.
+ return "none"
+ }
+}
+
// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
// api file for the current source
// TODO: remove this when apicheck is done in soong
@@ -417,14 +446,15 @@
props := struct {
Name *string
Srcs []string
+ Installable *bool
Sdk_version *string
+ System_modules *string
Libs []string
Soc_specific *bool
Device_specific *bool
Product_specific *bool
System_ext_specific *bool
Compile_dex *bool
- System_modules *string
Java_version *string
Product_variables struct {
Unbundled_build struct {
@@ -440,23 +470,19 @@
}
}{}
- sdkVersion := module.sdkVersion(apiScope)
- sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
- if !sdkDep.hasStandardLibs() {
- sdkVersion = "none"
- }
-
props.Name = proptools.StringPtr(module.stubsName(apiScope))
// sources are generated from the droiddoc
props.Srcs = []string{":" + module.docsName(apiScope)}
+ sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
props.Sdk_version = proptools.StringPtr(sdkVersion)
+ props.System_modules = module.Library.Module.deviceProperties.System_modules
+ props.Installable = proptools.BoolPtr(false)
props.Libs = module.sdkLibraryProperties.Stub_only_libs
// Unbundled apps will use the prebult one from /prebuilts/sdk
if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
}
props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
- props.System_modules = module.Library.Module.deviceProperties.System_modules
props.Openjdk9.Srcs = module.Library.Module.properties.Openjdk9.Srcs
props.Openjdk9.Javacflags = module.Library.Module.properties.Openjdk9.Javacflags
props.Java_version = module.Library.Module.properties.Java_version
@@ -479,12 +505,13 @@
// Creates a droiddoc module that creates stubs source files from the given full source
// files
-func (module *SdkLibrary) createDocs(mctx android.LoadHookContext, apiScope apiScope) {
+func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope apiScope) {
props := struct {
Name *string
Srcs []string
Installable *bool
Sdk_version *string
+ System_modules *string
Libs []string
Arg_files []string
Args *string
@@ -506,6 +533,8 @@
}{}
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ // Use the platform API if standard libraries were requested, otherwise use
+ // no default libraries.
sdkVersion := ""
if !sdkDep.hasStandardLibs() {
sdkVersion = "none"
@@ -514,6 +543,7 @@
props.Name = proptools.StringPtr(module.docsName(apiScope))
props.Srcs = append(props.Srcs, module.Library.Module.properties.Srcs...)
props.Sdk_version = proptools.StringPtr(sdkVersion)
+ props.System_modules = module.Library.Module.deviceProperties.System_modules
props.Installable = proptools.BoolPtr(false)
// A droiddoc module has only one Libs property and doesn't distinguish between
// shared libs and static libs. So we need to add both of these libs to Libs property.
@@ -526,21 +556,36 @@
props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
- droiddocArgs := " --stub-packages " + strings.Join(module.sdkLibraryProperties.Api_packages, ":") +
- " " + android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package ") +
- " " + android.JoinWithPrefix(module.sdkLibraryProperties.Droiddoc_options, " ") +
- " --hide MissingPermission --hide BroadcastBehavior " +
- "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
- "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
+ droiddocArgs := []string{}
+ if len(module.sdkLibraryProperties.Api_packages) != 0 {
+ droiddocArgs = append(droiddocArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
+ }
+ if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 {
+ droiddocArgs = append(droiddocArgs,
+ android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
+ }
+ droiddocArgs = append(droiddocArgs, module.sdkLibraryProperties.Droiddoc_options...)
+ disabledWarnings := []string{
+ "MissingPermission",
+ "BroadcastBehavior",
+ "HiddenSuperclass",
+ "DeprecationMismatch",
+ "UnavailableSymbol",
+ "SdkConstant",
+ "HiddenTypeParameter",
+ "Todo",
+ "Typo",
+ }
+ droiddocArgs = append(droiddocArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
switch apiScope {
case apiScopeSystem:
- droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
+ droiddocArgs = append(droiddocArgs, "-showAnnotation android.annotation.SystemApi")
case apiScopeTest:
- droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.TestApi"
+ droiddocArgs = append(droiddocArgs, " -showAnnotation android.annotation.TestApi")
}
props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
- props.Args = proptools.StringPtr(droiddocArgs)
+ props.Args = proptools.StringPtr(strings.Join(droiddocArgs, " "))
// List of APIs identified from the provided source files are created. They are later
// compared against to the not-yet-released (a.k.a current) list of APIs and to the
@@ -555,8 +600,9 @@
currentApiFileName = "test-" + currentApiFileName
removedApiFileName = "test-" + removedApiFileName
}
- currentApiFileName = path.Join("api", currentApiFileName)
- removedApiFileName = path.Join("api", removedApiFileName)
+ apiDir := module.getApiDir()
+ currentApiFileName = path.Join(apiDir, currentApiFileName)
+ removedApiFileName = path.Join(apiDir, removedApiFileName)
// TODO(jiyong): remove these three props
props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
props.Api_filename = proptools.StringPtr(currentApiFileName)
@@ -578,21 +624,6 @@
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
-
- // genrule to generate the xml file content from the template above
- // TODO: preserve newlines in the generate xml file. Newlines are being squashed
- // in the ninja file. Do we need to have an external tool for this?
- xmlContent := fmt.Sprintf(permissionTemplate, module.BaseModuleName(), module.implPath())
- genruleProps := struct {
- Name *string
- Cmd *string
- Out []string
- }{}
- genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
- genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
- genruleProps.Out = []string{module.xmlFileName()}
- mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
-
// creates a prebuilt_etc module to actually place the xml file under
// <partition>/etc/permissions
etcProps := struct {
@@ -605,7 +636,7 @@
System_ext_specific *bool
}{}
etcProps.Name = proptools.StringPtr(module.xmlFileName())
- etcProps.Src = proptools.StringPtr(":" + module.xmlFileName() + "-gen")
+ etcProps.Src = proptools.StringPtr(":" + module.BaseModuleName() + "{.xml}")
etcProps.Sub_dir = proptools.StringPtr("permissions")
if module.SocSpecific() {
etcProps.Soc_specific = proptools.BoolPtr(true)
@@ -686,6 +717,10 @@
}).(*[]string)
}
+func (module *SdkLibrary) getApiDir() string {
+ return proptools.StringDefault(module.sdkLibraryProperties.Api_dir, "api")
+}
+
// For a java_sdk_library module, create internal modules for stubs, docs,
// runtime libs and xml file. If requested, the stubs and docs are created twice
// once for public API level and once for system API level
@@ -695,16 +730,25 @@
return
}
- if len(module.sdkLibraryProperties.Api_packages) == 0 {
- mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
- return
+ // If this builds against standard libraries (i.e. is not part of the core libraries)
+ // then assume it provides both system and test apis. Otherwise, assume it does not and
+ // also assume it does not contribute to the dist build.
+ sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ hasSystemAndTestApis := sdkDep.hasStandardLibs()
+ module.sdkLibraryProperties.Has_system_and_test_apis = hasSystemAndTestApis
+ module.sdkLibraryProperties.No_dist = proptools.BoolPtr(!hasSystemAndTestApis)
+
+ scopes := []string{""}
+ if hasSystemAndTestApis {
+ scopes = append(scopes, "system-", "test-")
}
missing_current_api := false
- for _, scope := range []string{"", "system-", "test-"} {
+ apiDir := module.getApiDir()
+ for _, scope := range scopes {
for _, api := range []string{"current.txt", "removed.txt"} {
- path := path.Join(mctx.ModuleDir(), "api", scope+api)
+ path := path.Join(mctx.ModuleDir(), apiDir, scope+api)
p := android.ExistentPathForSource(mctx, path)
if !p.Valid() {
mctx.ModuleErrorf("Current api file %#v doesn't exist", path)
@@ -723,33 +767,35 @@
mctx.ModuleErrorf("One or more current api files are missing. "+
"You can update them by:\n"+
- "%s %q && m update-api", script, mctx.ModuleDir())
+ "%s %q %s && m update-api",
+ script, filepath.Join(mctx.ModuleDir(), apiDir), strings.Join(scopes, " "))
return
}
// for public API stubs
module.createStubsLibrary(mctx, apiScopePublic)
- module.createDocs(mctx, apiScopePublic)
+ module.createStubsSources(mctx, apiScopePublic)
- sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
- if sdkDep.hasStandardLibs() {
+ if hasSystemAndTestApis {
// for system API stubs
module.createStubsLibrary(mctx, apiScopeSystem)
- module.createDocs(mctx, apiScopeSystem)
+ module.createStubsSources(mctx, apiScopeSystem)
// for test API stubs
module.createStubsLibrary(mctx, apiScopeTest)
- module.createDocs(mctx, apiScopeTest)
-
- // for runtime
- module.createXmlFile(mctx)
+ module.createStubsSources(mctx, apiScopeTest)
}
- // record java_sdk_library modules so that they are exported to make
- javaSdkLibraries := javaSdkLibraries(mctx.Config())
- javaSdkLibrariesLock.Lock()
- defer javaSdkLibrariesLock.Unlock()
- *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
+ if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ // for runtime
+ module.createXmlFile(mctx)
+
+ // record java_sdk_library modules so that they are exported to make
+ javaSdkLibraries := javaSdkLibraries(mctx.Config())
+ javaSdkLibrariesLock.Lock()
+ defer javaSdkLibrariesLock.Unlock()
+ *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
+ }
}
func (module *SdkLibrary) InitSdkLibraryProperties() {
diff --git a/java/testing.go b/java/testing.go
index e157dd0..ab3af65 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -34,6 +34,7 @@
"GENRULE_NOTICE": nil,
"LIB_NOTICE": nil,
"TOOL_NOTICE": nil,
+ "AndroidTest.xml": nil,
"java-res/a/a": nil,
"java-res/b/b": nil,
"java-res2/a": nil,
diff --git a/rust/config/global.go b/rust/config/global.go
index 4d87780..ad8eb3a 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.37.0"
+ RustDefaultVersion = "1.40.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
new file mode 100755
index 0000000..7e3a82c
--- /dev/null
+++ b/scripts/build-aml-prebuilts.sh
@@ -0,0 +1,75 @@
+#!/bin/bash -e
+
+export OUT_DIR=${OUT_DIR:-out}
+
+if [ -e ${OUT_DIR}/soong/.soong.in_make ]; then
+ # If ${OUT_DIR} has been created without --skip-make, Soong will create an
+ # ${OUT_DIR}/soong/build.ninja that leaves out many targets which are
+ # expected to be supplied by the .mk files, and that might cause errors in
+ # "m --skip-make" below. We therefore default to a different out dir
+ # location in that case.
+ AML_OUT_DIR=out-aml
+ echo "Avoiding in-make OUT_DIR '${OUT_DIR}' - building in '${AML_OUT_DIR}' instead"
+ OUT_DIR=${AML_OUT_DIR}
+fi
+
+source build/envsetup.sh
+
+my_get_build_var() {
+ # get_build_var will run Soong in normal in-make mode where it creates
+ # .soong.in_make. That would clobber our real out directory, so we need to
+ # run it in a different one.
+ OUT_DIR=${OUT_DIR}/get_build_var get_build_var "$@"
+}
+
+PLATFORM_SDK_VERSION=$(my_get_build_var PLATFORM_SDK_VERSION)
+PLATFORM_VERSION=$(my_get_build_var PLATFORM_VERSION)
+PLATFORM_VERSION_ALL_CODENAMES=$(my_get_build_var PLATFORM_VERSION_ALL_CODENAMES)
+
+# PLATFORM_VERSION_ALL_CODENAMES is a comma separated list like O,P. We need to
+# turn this into ["O","P"].
+PLATFORM_VERSION_ALL_CODENAMES=${PLATFORM_VERSION_ALL_CODENAMES/,/'","'}
+PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
+
+# Logic from build/make/core/goma.mk
+if [ "${USE_GOMA}" = true ]; then
+ if [ -n "${GOMA_DIR}" ]; then
+ goma_dir="${GOMA_DIR}"
+ else
+ goma_dir="${HOME}/goma"
+ fi
+ GOMA_CC="${goma_dir}/gomacc"
+ export CC_WRAPPER="${CC_WRAPPER}${CC_WRAPPER:+ }${GOMA_CC}"
+ export CXX_WRAPPER="${CXX_WRAPPER}${CXX_WRAPPER:+ }${GOMA_CC}"
+ export JAVAC_WRAPPER="${JAVAC_WRAPPER}${JAVAC_WRAPPER:+ }${GOMA_CC}"
+else
+ USE_GOMA=false
+fi
+
+SOONG_OUT=${OUT_DIR}/soong
+mkdir -p ${SOONG_OUT}
+SOONG_VARS=${SOONG_OUT}/soong.variables
+
+cat > ${SOONG_VARS}.new << EOF
+{
+ "Platform_sdk_version": ${PLATFORM_SDK_VERSION},
+ "Platform_sdk_codename": "${PLATFORM_VERSION}",
+ "Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
+
+ "DeviceName": "generic_arm64",
+ "HostArch": "x86_64",
+ "Aml_abis": true,
+
+ "UseGoma": ${USE_GOMA}
+}
+EOF
+
+if [ -f ${SOONG_VARS} ] && cmp -s ${SOONG_VARS} ${SOONG_VARS}.new; then
+ # Don't touch soong.variables if we don't have to, to avoid Soong rebuilding
+ # the ninja file when it isn't necessary.
+ rm ${SOONG_VARS}.new
+else
+ mv ${SOONG_VARS}.new ${SOONG_VARS}
+fi
+
+m --skip-make "$@"
diff --git a/scripts/gen-java-current-api-files.sh b/scripts/gen-java-current-api-files.sh
index 517d391..547387a 100755
--- a/scripts/gen-java-current-api-files.sh
+++ b/scripts/gen-java-current-api-files.sh
@@ -15,15 +15,16 @@
# limitations under the License.
if [[ -z "$1" ]]; then
- echo "usage: $0 <modulePath>" >&2
+ echo "usage: $0 <modulePath> scopes..." >&2
exit 1
fi
-api_dir=$1/api
+api_dir=$1
+shift
mkdir -p "$api_dir"
-scopes=("" system- test-)
+scopes=("" "$@")
apis=(current removed)
for scope in "${scopes[@]}"; do
@@ -31,3 +32,4 @@
touch "${api_dir}/${scope}${api}.txt"
done
done
+
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 08751e4..255ac08 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -73,6 +73,10 @@
native_shared_libs: ["sdkmember"],
}
+ cc_library_shared {
+ name: "sdkmember",
+ }
+
sdk_snapshot {
name: "mysdk@1",
native_shared_libs: ["sdkmember_mysdk_1"],
@@ -143,6 +147,66 @@
ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
}
+// Make sure the sdk can use host specific cc libraries static/shared and both.
+func TestHostSdkWithCc(t *testing.T) {
+ testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ device_supported: false,
+ host_supported: true,
+ native_shared_libs: ["sdkshared"],
+ native_static_libs: ["sdkstatic"],
+ }
+
+ cc_library_host_shared {
+ name: "sdkshared",
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library_host_static {
+ name: "sdkstatic",
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+}
+
+// Make sure the sdk can use cc libraries static/shared and both.
+func TestSdkWithCc(t *testing.T) {
+ testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_shared_libs: ["sdkshared", "sdkboth1"],
+ native_static_libs: ["sdkstatic", "sdkboth2"],
+ }
+
+ cc_library_shared {
+ name: "sdkshared",
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library_static {
+ name: "sdkstatic",
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "sdkboth1",
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "sdkboth2",
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+}
+
func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
@@ -436,8 +500,8 @@
func TestSnapshotWithCcStaticLibrary(t *testing.T) {
result := testSdkWithCc(t, `
- sdk {
- name: "mysdk",
+ module_exports {
+ name: "myexports",
native_static_libs: ["mynativelib"],
}
@@ -456,12 +520,12 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("myexports", "android_common", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static {
- name: "mysdk_mynativelib@current",
+ name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
export_include_dirs: ["include/include"],
arch: {
@@ -496,9 +560,9 @@
system_shared_libs: [],
}
-sdk_snapshot {
- name: "mysdk@current",
- native_static_libs: ["mysdk_mynativelib@current"],
+module_exports_snapshot {
+ name: "myexports@current",
+ native_static_libs: ["myexports_mynativelib@current"],
}
`),
checkAllCopyRules(`
@@ -520,8 +584,8 @@
SkipIfNotLinux(t)
result := testSdkWithCc(t, `
- sdk {
- name: "mysdk",
+ module_exports {
+ name: "myexports",
device_supported: false,
host_supported: true,
native_static_libs: ["mynativelib"],
@@ -544,12 +608,12 @@
}
`)
- result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "linux_glibc_common", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static {
- name: "mysdk_mynativelib@current",
+ name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
device_supported: false,
host_supported: true,
@@ -588,11 +652,11 @@
system_shared_libs: [],
}
-sdk_snapshot {
- name: "mysdk@current",
+module_exports_snapshot {
+ name: "myexports@current",
device_supported: false,
host_supported: true,
- native_static_libs: ["mysdk_mynativelib@current"],
+ native_static_libs: ["myexports_mynativelib@current"],
}
`),
checkAllCopyRules(`
diff --git a/sdk/exports.go b/sdk/exports.go
new file mode 100644
index 0000000..d313057
--- /dev/null
+++ b/sdk/exports.go
@@ -0,0 +1,36 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sdk
+
+import "android/soong/android"
+
+func init() {
+ android.RegisterModuleType("module_exports", ModuleExportsFactory)
+ android.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
+}
+
+// module_exports defines the exports of a mainline module. The exports are Soong modules
+// which are required by Soong modules that are not part of the mainline module.
+func ModuleExportsFactory() android.Module {
+ return newSdkModule(true)
+}
+
+// module_exports_snapshot is a versioned snapshot of prebuilt versions of all the exports
+// of a mainline module.
+func ModuleExportsSnapshotsFactory() android.Module {
+ s := newSdkModule(true)
+ s.properties.Snapshot = true
+ return s
+}
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
new file mode 100644
index 0000000..b905d71
--- /dev/null
+++ b/sdk/exports_test.go
@@ -0,0 +1,66 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sdk
+
+import (
+ "testing"
+)
+
+// Ensure that module_exports generates a module_exports_snapshot module.
+func TestModuleExportsSnapshot(t *testing.T) {
+ packageBp := `
+ module_exports {
+ name: "myexports",
+ java_libs: [
+ "myjavalib",
+ ],
+ }
+
+ java_library {
+ name: "myjavalib",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ }
+ `
+
+ result := testSdkWithFs(t, ``,
+ map[string][]byte{
+ "package/Test.java": nil,
+ "package/Android.bp": []byte(packageBp),
+ })
+
+ result.CheckSnapshot("myexports", "android_common", "package",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+ name: "myexports_myjavalib@current",
+ sdk_member_name: "myjavalib",
+ jars: ["java/myjavalib.jar"],
+}
+
+java_import {
+ name: "myjavalib",
+ prefer: false,
+ jars: ["java/myjavalib.jar"],
+}
+
+module_exports_snapshot {
+ name: "myexports@current",
+ java_libs: ["myexports_myjavalib@current"],
+}
+`))
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 1aa9184..218a16a 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -214,8 +214,8 @@
func TestSnapshotWithJavaImplLibrary(t *testing.T) {
result := testSdkWithJava(t, `
- sdk {
- name: "mysdk",
+ module_exports {
+ name: "myexports",
java_libs: ["myjavalib"],
}
@@ -232,12 +232,12 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("myexports", "android_common", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
java_import {
- name: "mysdk_myjavalib@current",
+ name: "myexports_myjavalib@current",
sdk_member_name: "myjavalib",
jars: ["java/myjavalib.jar"],
}
@@ -248,9 +248,9 @@
jars: ["java/myjavalib.jar"],
}
-sdk_snapshot {
- name: "mysdk@current",
- java_libs: ["mysdk_myjavalib@current"],
+module_exports_snapshot {
+ name: "myexports@current",
+ java_libs: ["myexports_myjavalib@current"],
}
`),
@@ -266,8 +266,8 @@
SkipIfNotLinux(t)
result := testSdkWithJava(t, `
- sdk {
- name: "mysdk",
+ module_exports {
+ name: "myexports",
device_supported: false,
host_supported: true,
java_libs: ["myjavalib"],
@@ -287,12 +287,12 @@
}
`)
- result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "linux_glibc_common", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
java_import {
- name: "mysdk_myjavalib@current",
+ name: "myexports_myjavalib@current",
sdk_member_name: "myjavalib",
device_supported: false,
host_supported: true,
@@ -307,11 +307,11 @@
jars: ["java/myjavalib.jar"],
}
-sdk_snapshot {
- name: "mysdk@current",
+module_exports_snapshot {
+ name: "myexports@current",
device_supported: false,
host_supported: true,
- java_libs: ["mysdk_myjavalib@current"],
+ java_libs: ["myexports_myjavalib@current"],
}
`),
checkAllCopyRules(`
@@ -321,6 +321,112 @@
)
}
+func TestSnapshotWithJavaTest(t *testing.T) {
+ result := testSdkWithJava(t, `
+ module_exports {
+ name: "myexports",
+ java_tests: ["myjavatests"],
+ }
+
+ java_test {
+ name: "myjavatests",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ host_supported: true,
+ }
+ `)
+
+ result.CheckSnapshot("myexports", "android_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_test_import {
+ name: "myexports_myjavatests@current",
+ sdk_member_name: "myjavatests",
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+java_test_import {
+ name: "myjavatests",
+ prefer: false,
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+module_exports_snapshot {
+ name: "myexports@current",
+ java_tests: ["myexports_myjavatests@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavatests/android_common/javac/myjavatests.jar -> java/myjavatests.jar
+.intermediates/myjavatests/android_common/myjavatests.config -> java/myjavatests-AndroidTest.xml
+`),
+ )
+}
+
+func TestHostSnapshotWithJavaTest(t *testing.T) {
+ // b/145598135 - Generating host snapshots for anything other than linux is not supported.
+ SkipIfNotLinux(t)
+
+ result := testSdkWithJava(t, `
+ module_exports {
+ name: "myexports",
+ device_supported: false,
+ host_supported: true,
+ java_tests: ["myjavatests"],
+ }
+
+ java_test {
+ name: "myjavatests",
+ device_supported: false,
+ host_supported: true,
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ }
+ `)
+
+ result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_test_import {
+ name: "myexports_myjavatests@current",
+ sdk_member_name: "myjavatests",
+ device_supported: false,
+ host_supported: true,
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+java_test_import {
+ name: "myjavatests",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+module_exports_snapshot {
+ name: "myexports@current",
+ device_supported: false,
+ host_supported: true,
+ java_tests: ["myexports_myjavatests@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavatests/linux_glibc_common/javac/myjavatests.jar -> java/myjavatests.jar
+.intermediates/myjavatests/linux_glibc_common/myjavatests.config -> java/myjavatests-AndroidTest.xml
+`),
+ )
+}
+
func testSdkWithDroidstubs(t *testing.T, bp string) *testSdkResult {
t.Helper()
@@ -366,8 +472,8 @@
func TestSnapshotWithDroidstubs(t *testing.T) {
result := testSdkWithDroidstubs(t, `
- sdk {
- name: "mysdk",
+ module_exports {
+ name: "myexports",
stubs_sources: ["myjavaapistubs"],
}
@@ -379,12 +485,12 @@
}
`)
- result.CheckSnapshot("mysdk", "android_common", "",
+ result.CheckSnapshot("myexports", "android_common", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
prebuilt_stubs_sources {
- name: "mysdk_myjavaapistubs@current",
+ name: "myexports_myjavaapistubs@current",
sdk_member_name: "myjavaapistubs",
srcs: ["java/myjavaapistubs_stubs_sources"],
}
@@ -395,14 +501,14 @@
srcs: ["java/myjavaapistubs_stubs_sources"],
}
-sdk_snapshot {
- name: "mysdk@current",
- stubs_sources: ["mysdk_myjavaapistubs@current"],
+module_exports_snapshot {
+ name: "myexports@current",
+ stubs_sources: ["myexports_myjavaapistubs@current"],
}
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/mysdk/android_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZip(".intermediates/myexports/android_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
@@ -411,8 +517,8 @@
SkipIfNotLinux(t)
result := testSdkWithDroidstubs(t, `
- sdk {
- name: "mysdk",
+ module_exports {
+ name: "myexports",
device_supported: false,
host_supported: true,
stubs_sources: ["myjavaapistubs"],
@@ -428,12 +534,12 @@
}
`)
- result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ result.CheckSnapshot("myexports", "linux_glibc_common", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
prebuilt_stubs_sources {
- name: "mysdk_myjavaapistubs@current",
+ name: "myexports_myjavaapistubs@current",
sdk_member_name: "myjavaapistubs",
device_supported: false,
host_supported: true,
@@ -448,14 +554,14 @@
srcs: ["java/myjavaapistubs_stubs_sources"],
}
-sdk_snapshot {
- name: "mysdk@current",
+module_exports_snapshot {
+ name: "myexports@current",
device_supported: false,
host_supported: true,
- stubs_sources: ["mysdk_myjavaapistubs@current"],
+ stubs_sources: ["myexports_myjavaapistubs@current"],
}
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/mysdk/linux_glibc_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZip(".intermediates/myexports/linux_glibc_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 62bc06f..44e5cbb 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -33,7 +33,7 @@
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
- android.RegisterModuleType("sdk", ModuleFactory)
+ android.RegisterModuleType("sdk", SdkModuleFactory)
android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
android.PreDepsMutators(RegisterPreDepsMutators)
android.PostDepsMutators(RegisterPostDepsMutators)
@@ -60,6 +60,9 @@
type sdkProperties struct {
Snapshot bool `blueprint:"mutated"`
+
+ // True if this is a module_exports (or module_exports_snapshot) module type.
+ Module_exports bool `blueprint:"mutated"`
}
type sdkMemberDependencyTag struct {
@@ -130,6 +133,7 @@
// * a dependency tag that identifies the member type of a resolved dependency.
//
func createDynamicSdkMemberTypes(sdkMemberTypes []android.SdkMemberType) *dynamicSdkMemberTypes {
+
var listProperties []*sdkMemberListProperty
var fields []reflect.StructField
@@ -182,18 +186,25 @@
// sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
// which Mainline modules like APEX can choose to build with.
-func ModuleFactory() android.Module {
+func SdkModuleFactory() android.Module {
+ return newSdkModule(false)
+}
+
+func newSdkModule(moduleExports bool) *sdk {
s := &sdk{}
-
+ s.properties.Module_exports = moduleExports
// Get the dynamic sdk member type data for the currently registered sdk member types.
- s.dynamicSdkMemberTypes = getDynamicSdkMemberTypes(android.SdkMemberTypes)
-
+ var registry *android.SdkMemberTypesRegistry
+ if moduleExports {
+ registry = android.ModuleExportsMemberTypes
+ } else {
+ registry = android.SdkMemberTypes
+ }
+ s.dynamicSdkMemberTypes = getDynamicSdkMemberTypes(registry)
// Create an instance of the dynamically created struct that contains all the
// properties for the member type specific list properties.
s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties()
-
s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties)
-
android.InitAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(s)
android.AddLoadHook(s, func(ctx android.LoadHookContext) {
@@ -208,8 +219,8 @@
// sdk_snapshot is a versioned snapshot of an SDK. This is an auto-generated module.
func SnapshotModuleFactory() android.Module {
- s := ModuleFactory()
- s.(*sdk).properties.Snapshot = true
+ s := newSdkModule(false)
+ s.properties.Snapshot = true
return s
}
diff --git a/sdk/testing.go b/sdk/testing.go
index eec7f01..8097889 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -77,8 +77,6 @@
// from cc package
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
- ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
// from apex package
ctx.RegisterModuleType("apex", apex.BundleFactory)
@@ -86,8 +84,10 @@
ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
// from this package
- ctx.RegisterModuleType("sdk", ModuleFactory)
+ ctx.RegisterModuleType("sdk", SdkModuleFactory)
ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
+ ctx.RegisterModuleType("module_exports", ModuleExportsFactory)
+ ctx.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
@@ -185,7 +185,7 @@
switch bp.Rule.String() {
case android.Cp.String():
// Get source relative to build directory.
- src := r.pathRelativeToBuildDir(bp.Input)
+ src := android.NormalizePathForTesting(bp.Input)
// Get destination relative to the snapshot root
dest := bp.Output.Rel()
_, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest)
@@ -201,12 +201,12 @@
// This could be an intermediate zip file and not the actual output zip.
// In that case this will be overridden when the rule to merge the zips
// is processed.
- info.outputZip = r.pathRelativeToBuildDir(bp.Output)
+ info.outputZip = android.NormalizePathForTesting(bp.Output)
case mergeZips.String():
// Copy the current outputZip to the intermediateZip.
info.intermediateZip = info.outputZip
- mergeInput := r.pathRelativeToBuildDir(bp.Input)
+ mergeInput := android.NormalizePathForTesting(bp.Input)
if info.intermediateZip != mergeInput {
r.t.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
info.intermediateZip, mergeInput)
@@ -214,10 +214,10 @@
// Override output zip (which was actually the intermediate zip file) with the actual
// output zip.
- info.outputZip = r.pathRelativeToBuildDir(bp.Output)
+ info.outputZip = android.NormalizePathForTesting(bp.Output)
// Save the zips to be merged into the intermediate zip.
- info.mergeZips = r.pathsRelativeToBuildDir(bp.Inputs)
+ info.mergeZips = android.NormalizePathsForTesting(bp.Inputs)
}
}
@@ -234,19 +234,6 @@
return r.ctx.ModuleForTests(name, variant)
}
-func (r *testSdkResult) pathRelativeToBuildDir(path android.Path) string {
- buildDir := filepath.Clean(r.config.BuildDir()) + "/"
- return strings.TrimPrefix(filepath.Clean(path.String()), buildDir)
-}
-
-func (r *testSdkResult) pathsRelativeToBuildDir(paths android.Paths) []string {
- var result []string
- for _, path := range paths {
- result = append(result, r.pathRelativeToBuildDir(path))
- }
- return result
-}
-
// Check the snapshot build rules.
//
// Takes a list of functions which check different facets of the snapshot build rules.
diff --git a/sdk/update.go b/sdk/update.go
index d31fa30..5bc3b83 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -209,7 +209,13 @@
// Create the snapshot module.
snapshotName := ctx.ModuleName() + string(android.SdkVersionSeparator) + builder.version
- snapshotModule := bpFile.newModule("sdk_snapshot")
+ var snapshotModuleType string
+ if s.properties.Module_exports {
+ snapshotModuleType = "module_exports_snapshot"
+ } else {
+ snapshotModuleType = "sdk_snapshot"
+ }
+ snapshotModule := bpFile.newModule(snapshotModuleType)
snapshotModule.AddProperty("name", snapshotName)
// Make sure that the snapshot has the same visibility as the sdk.
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 0c0f222..7cad3da 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -66,8 +66,6 @@
})
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
- ctx.RegisterModuleType("cc_library_static", cc.LibraryFactory)
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel()
})
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 6f81c17..2a5a51a 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -59,6 +59,7 @@
"util.go",
],
testSrcs: [
+ "cleanbuild_test.go",
"config_test.go",
"environment_test.go",
"util_test.go",
@@ -66,11 +67,13 @@
],
darwin: {
srcs: [
+ "config_darwin.go",
"sandbox_darwin.go",
],
},
linux: {
srcs: [
+ "config_linux.go",
"sandbox_linux.go",
],
},
diff --git a/ui/build/build.go b/ui/build/build.go
index 7dfb900..1c2d864 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -137,6 +137,7 @@
func Build(ctx Context, config Config, what int) {
ctx.Verboseln("Starting build with args:", config.Arguments())
ctx.Verboseln("Environment:", config.Environment().Environ())
+ ctx.Verbosef("Total RAM: %dGB", config.TotalRAM()/1024/1024/1024)
if config.SkipMake() {
ctx.Verboseln("Skipping Make/Kati as requested")
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 0b44b4d..1c4f574 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -15,10 +15,12 @@
package build
import (
+ "bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
+ "sort"
"strings"
"android/soong/ui/metrics"
@@ -177,3 +179,78 @@
writeConfig()
}
+
+// cleanOldFiles takes an input file (with all paths relative to basePath), and removes files from
+// the filesystem if they were removed from the input file since the last execution.
+func cleanOldFiles(ctx Context, basePath, file string) {
+ file = filepath.Join(basePath, file)
+ oldFile := file + ".previous"
+
+ if _, err := os.Stat(file); err != nil {
+ ctx.Fatalf("Expected %q to be readable", file)
+ }
+
+ if _, err := os.Stat(oldFile); os.IsNotExist(err) {
+ if err := os.Rename(file, oldFile); err != nil {
+ ctx.Fatalf("Failed to rename file list (%q->%q): %v", file, oldFile, err)
+ }
+ return
+ }
+
+ var newPaths, oldPaths []string
+ if newData, err := ioutil.ReadFile(file); err == nil {
+ if oldData, err := ioutil.ReadFile(oldFile); err == nil {
+ // Common case: nothing has changed
+ if bytes.Equal(newData, oldData) {
+ return
+ }
+ newPaths = strings.Fields(string(newData))
+ oldPaths = strings.Fields(string(oldData))
+ } else {
+ ctx.Fatalf("Failed to read list of installable files (%q): %v", oldFile, err)
+ }
+ } else {
+ ctx.Fatalf("Failed to read list of installable files (%q): %v", file, err)
+ }
+
+ // These should be mostly sorted by make already, but better make sure Go concurs
+ sort.Strings(newPaths)
+ sort.Strings(oldPaths)
+
+ for len(oldPaths) > 0 {
+ if len(newPaths) > 0 {
+ if oldPaths[0] == newPaths[0] {
+ // Same file; continue
+ newPaths = newPaths[1:]
+ oldPaths = oldPaths[1:]
+ continue
+ } else if oldPaths[0] > newPaths[0] {
+ // New file; ignore
+ newPaths = newPaths[1:]
+ continue
+ }
+ }
+ // File only exists in the old list; remove if it exists
+ old := filepath.Join(basePath, oldPaths[0])
+ oldPaths = oldPaths[1:]
+ if fi, err := os.Stat(old); err == nil {
+ if fi.IsDir() {
+ if err := os.Remove(old); err == nil {
+ ctx.Println("Removed directory that is no longer installed: ", old)
+ } else {
+ ctx.Println("Failed to remove directory that is no longer installed (%q): %v", old, err)
+ ctx.Println("It's recommended to run `m installclean`")
+ }
+ } else {
+ if err := os.Remove(old); err == nil {
+ ctx.Println("Removed file that is no longer installed: ", old)
+ } else if !os.IsNotExist(err) {
+ ctx.Fatalf("Failed to remove file that is no longer installed (%q): %v", old, err)
+ }
+ }
+ }
+ }
+
+ // Use the new list as the base for the next build
+ os.Rename(file, oldFile)
+}
diff --git a/ui/build/cleanbuild_test.go b/ui/build/cleanbuild_test.go
new file mode 100644
index 0000000..89f4ad9
--- /dev/null
+++ b/ui/build/cleanbuild_test.go
@@ -0,0 +1,100 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import (
+ "android/soong/ui/logger"
+ "bytes"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "strings"
+ "testing"
+)
+
+func TestCleanOldFiles(t *testing.T) {
+ dir, err := ioutil.TempDir("", "testcleanoldfiles")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+
+ ctx := testContext()
+ logBuf := &bytes.Buffer{}
+ ctx.Logger = logger.New(logBuf)
+
+ touch := func(names ...string) {
+ for _, name := range names {
+ if f, err := os.Create(filepath.Join(dir, name)); err != nil {
+ t.Fatal(err)
+ } else {
+ f.Close()
+ }
+ }
+ }
+ runCleanOldFiles := func(names ...string) {
+ data := []byte(strings.Join(names, " "))
+ if err := ioutil.WriteFile(filepath.Join(dir, ".installed"), data, 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ cleanOldFiles(ctx, dir, ".installed")
+ }
+
+ assertFileList := func(names ...string) {
+ t.Helper()
+
+ sort.Strings(names)
+
+ var foundNames []string
+ if foundFiles, err := ioutil.ReadDir(dir); err == nil {
+ for _, fi := range foundFiles {
+ foundNames = append(foundNames, fi.Name())
+ }
+ } else {
+ t.Fatal(err)
+ }
+
+ if !reflect.DeepEqual(names, foundNames) {
+ t.Errorf("Expected a different list of files:\nwant: %v\n got: %v", names, foundNames)
+ t.Error("Log: ", logBuf.String())
+ logBuf.Reset()
+ }
+ }
+
+ // Initial list of potential files
+ runCleanOldFiles("foo", "bar")
+ touch("foo", "bar", "baz")
+ assertFileList("foo", "bar", "baz", ".installed.previous")
+
+ // This should be a no-op, as the list hasn't changed
+ runCleanOldFiles("foo", "bar")
+ assertFileList("foo", "bar", "baz", ".installed", ".installed.previous")
+
+ // This should be a no-op, as only a file was added
+ runCleanOldFiles("foo", "bar", "foo2")
+ assertFileList("foo", "bar", "baz", ".installed.previous")
+
+ // "bar" should be removed, foo2 should be ignored as it was never there
+ runCleanOldFiles("foo")
+ assertFileList("foo", "baz", ".installed.previous")
+
+ // Recreate bar, and create foo2. Ensure that they aren't removed
+ touch("bar", "foo2")
+ runCleanOldFiles("foo", "baz")
+ assertFileList("foo", "bar", "baz", "foo2", ".installed.previous")
+}
diff --git a/ui/build/config.go b/ui/build/config.go
index 565f033..c084171 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -50,10 +50,14 @@
targetDevice string
targetDeviceDir string
+ // Autodetected
+ totalRAM uint64
+
pdkBuild bool
- brokenDupRules bool
- brokenUsesNetwork bool
+ brokenDupRules bool
+ brokenUsesNetwork bool
+ brokenNinjaEnvVars []string
pathReplaced bool
}
@@ -96,6 +100,8 @@
ret.parallel = runtime.NumCPU() + 2
ret.keepGoing = 1
+ ret.totalRAM = detectTotalRAM(ctx)
+
ret.parseArgs(ctx, args)
// Make sure OUT_DIR is set appropriately
@@ -716,6 +722,10 @@
return c.parallel
}
+func (c *configImpl) TotalRAM() uint64 {
+ return c.totalRAM
+}
+
func (c *configImpl) UseGoma() bool {
if v, ok := c.environ.Get("USE_GOMA"); ok {
v = strings.TrimSpace(v)
@@ -898,6 +908,14 @@
return c.brokenUsesNetwork
}
+func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
+ c.brokenNinjaEnvVars = val
+}
+
+func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
+ return c.brokenNinjaEnvVars
+}
+
func (c *configImpl) SetTargetDeviceDir(dir string) {
c.targetDeviceDir = dir
}
diff --git a/ui/build/config_darwin.go b/ui/build/config_darwin.go
new file mode 100644
index 0000000..480d8d1
--- /dev/null
+++ b/ui/build/config_darwin.go
@@ -0,0 +1,40 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import (
+ "encoding/binary"
+ "syscall"
+)
+
+func detectTotalRAM(ctx Context) uint64 {
+ s, err := syscall.Sysctl("hw.memsize")
+ if err != nil {
+ ctx.Printf("Failed to get system memory size: %s")
+ return 0
+ }
+
+ // syscall.Sysctl assumes that the return value is a string and trims the last byte if it is 0.
+ if len(s) == 7 {
+ s += "\x00"
+ }
+
+ if len(s) != 8 {
+ ctx.Printf("Failed to get system memory size, returned %d bytes, 8", len(s))
+ return 0
+ }
+
+ return binary.LittleEndian.Uint64([]byte(s))
+}
diff --git a/ui/build/config_linux.go b/ui/build/config_linux.go
new file mode 100644
index 0000000..9e1bdc7
--- /dev/null
+++ b/ui/build/config_linux.go
@@ -0,0 +1,28 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import "syscall"
+
+func detectTotalRAM(ctx Context) uint64 {
+ var info syscall.Sysinfo_t
+ err := syscall.Sysinfo(&info)
+ if err != nil {
+ ctx.Printf("Failed to get system memory size: %s")
+ return 0
+ }
+ memBytes := uint64(info.Totalram) * uint64(info.Unit)
+ return memBytes
+}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 4270bb1..c3da38b 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -216,6 +216,9 @@
// Whether to enable the network during the build
"BUILD_BROKEN_USES_NETWORK",
+ // Extra environment variables to be exported to ninja
+ "BUILD_BROKEN_NINJA_USES_ENV_VARS",
+
// Not used, but useful to be in the soong.log
"BOARD_VNDK_VERSION",
@@ -284,4 +287,5 @@
config.SetPdkBuild(make_vars["TARGET_BUILD_PDK"] == "true")
config.SetBuildBrokenDupRules(make_vars["BUILD_BROKEN_DUP_RULES"] == "true")
config.SetBuildBrokenUsesNetwork(make_vars["BUILD_BROKEN_USES_NETWORK"] == "true")
+ config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(make_vars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
}
diff --git a/ui/build/kati.go b/ui/build/kati.go
index ac09ce1..a845c5b 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -153,6 +153,7 @@
runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
cleanCopyHeaders(ctx, config)
+ cleanOldInstalledFiles(ctx, config)
}
func cleanCopyHeaders(ctx Context, config Config) {
@@ -192,6 +193,23 @@
})
}
+func cleanOldInstalledFiles(ctx Context, config Config) {
+ ctx.BeginTrace("clean", "clean old installed files")
+ defer ctx.EndTrace()
+
+ // We shouldn't be removing files from one side of the two-step asan builds
+ var suffix string
+ if v, ok := config.Environment().Get("SANITIZE_TARGET"); ok {
+ if sanitize := strings.Fields(v); inList("address", sanitize) {
+ suffix = "_asan"
+ }
+ }
+
+ cleanOldFiles(ctx, config.ProductOut(), ".installable_files"+suffix)
+
+ cleanOldFiles(ctx, config.HostOut(), ".installable_test_files")
+}
+
func runKatiPackage(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunKati, "kati package")
defer ctx.EndTrace()
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index d5baafe..6775ccf 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -18,6 +18,7 @@
"fmt"
"os"
"path/filepath"
+ "sort"
"strconv"
"strings"
"time"
@@ -65,8 +66,6 @@
cmd.Environment.AppendFromKati(config.KatiEnvFile())
}
- cmd.Environment.Set("DIST_DIR", config.DistDir())
-
// Allow both NINJA_ARGS and NINJA_EXTRA_ARGS, since both have been
// used in the past to specify extra ninja arguments.
if extra, ok := cmd.Environment.Get("NINJA_ARGS"); ok {
@@ -85,6 +84,72 @@
ninjaHeartbeatDuration = overrideDuration
}
}
+
+ // Filter the environment, as ninja does not rebuild files when environment variables change.
+ //
+ // Anything listed here must not change the output of rules/actions when the value changes,
+ // otherwise incremental builds may be unsafe. Vars explicitly set to stable values
+ // elsewhere in soong_ui are fine.
+ //
+ // For the majority of cases, either Soong or the makefiles should be replicating any
+ // necessary environment variables in the command line of each action that needs it.
+ if cmd.Environment.IsEnvTrue("ALLOW_NINJA_ENV") {
+ ctx.Println("Allowing all environment variables during ninja; incremental builds may be unsafe.")
+ } else {
+ cmd.Environment.Allow(append([]string{
+ "ASAN_SYMBOLIZER_PATH",
+ "HOME",
+ "JAVA_HOME",
+ "LANG",
+ "LC_MESSAGES",
+ "OUT_DIR",
+ "PATH",
+ "PWD",
+ "PYTHONDONTWRITEBYTECODE",
+ "TMPDIR",
+ "USER",
+
+ // TODO: remove these carefully
+ "ASAN_OPTIONS",
+ "TARGET_BUILD_APPS",
+ "TARGET_BUILD_VARIANT",
+ "TARGET_PRODUCT",
+
+ // Goma -- gomacc may not need all of these
+ "GOMA_DIR",
+ "GOMA_DISABLED",
+ "GOMA_FAIL_FAST",
+ "GOMA_FALLBACK",
+ "GOMA_GCE_SERVICE_ACCOUNT",
+ "GOMA_TMP_DIR",
+ "GOMA_USE_LOCAL",
+
+ // RBE client
+ "FLAG_exec_root",
+ "FLAG_exec_strategy",
+ "FLAG_invocation_id",
+ "FLAG_log_dir",
+ "FLAG_platform",
+ "FLAG_server_address",
+
+ // ccache settings
+ "CCACHE_COMPILERCHECK",
+ "CCACHE_SLOPPINESS",
+ "CCACHE_BASEDIR",
+ "CCACHE_CPP2",
+ }, config.BuildBrokenNinjaUsesEnvVars()...)...)
+ }
+
+ cmd.Environment.Set("DIST_DIR", config.DistDir())
+ cmd.Environment.Set("SHELL", "/bin/bash")
+
+ ctx.Verboseln("Ninja environment: ")
+ envVars := cmd.Environment.Environ()
+ sort.Strings(envVars)
+ for _, envVar := range envVars {
+ ctx.Verbosef(" %s", envVar)
+ }
+
// Poll the ninja log for updates; if it isn't updated enough, then we want to show some diagnostics
done := make(chan struct{})
defer close(done)
diff --git a/ui/status/critical_path.go b/ui/status/critical_path.go
index 444327b..8065c60 100644
--- a/ui/status/critical_path.go
+++ b/ui/status/critical_path.go
@@ -112,8 +112,10 @@
if !cp.start.IsZero() {
elapsedTime := cp.end.Sub(cp.start).Round(time.Second)
cp.log.Verbosef("elapsed time %s", elapsedTime.String())
- cp.log.Verbosef("perfect parallelism ratio %d%%",
- int(float64(criticalTime)/float64(elapsedTime)*100))
+ if elapsedTime > 0 {
+ cp.log.Verbosef("perfect parallelism ratio %d%%",
+ int(float64(criticalTime)/float64(elapsedTime)*100))
+ }
}
cp.log.Verbose("critical path:")
for i := len(criticalPath) - 1; i >= 0; i-- {
diff --git a/vnames.go.json b/vnames.go.json
new file mode 100644
index 0000000..5842097
--- /dev/null
+++ b/vnames.go.json
@@ -0,0 +1,9 @@
+[
+ {
+ "pattern": "(.*)",
+ "vname": {
+ "corpus": "android.googlesource.com/platform/superproject",
+ "path": "build/soong/@1@"
+ }
+ }
+]