Merge "rust: Refactor staticStd to stdLinkage"
diff --git a/android/androidmk.go b/android/androidmk.go
index e90e5f0..ddd51ff 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -639,3 +639,21 @@
// Make does not understand LinuxBionic
module.Os() == LinuxBionic
}
+
+func AndroidMkDataPaths(data []DataPath) []string {
+ var testFiles []string
+ for _, d := range data {
+ rel := d.SrcPath.Rel()
+ path := d.SrcPath.String()
+ if !strings.HasSuffix(path, rel) {
+ panic(fmt.Errorf("path %q does not end with %q", path, rel))
+ }
+ path = strings.TrimSuffix(path, rel)
+ testFileString := path + ":" + rel
+ if len(d.RelativeInstallPath) > 0 {
+ testFileString += ":" + d.RelativeInstallPath
+ }
+ testFiles = append(testFiles, testFileString)
+ }
+ return testFiles
+}
diff --git a/android/apex.go b/android/apex.go
index 3cc663b..7ae46d4 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -136,7 +136,7 @@
// Returns the highest version which is <= maxSdkVersion.
// For example, with maxSdkVersion is 10 and versionList is [9,11]
// it returns 9 as string
- ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error)
+ ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error)
// Tests if the module comes from an updatable APEX.
Updatable() bool
@@ -320,14 +320,18 @@
return true
}
-func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error) {
+func (m *ApexModuleBase) ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error) {
for i := range versionList {
- ver, _ := strconv.Atoi(versionList[len(versionList)-i-1])
- if ver <= maxSdkVersion {
- return versionList[len(versionList)-i-1], nil
+ version := versionList[len(versionList)-i-1]
+ ver, err := ApiLevelFromUser(ctx, version)
+ if err != nil {
+ return "", err
+ }
+ if ver.LessThanOrEqualTo(maxSdkVersion) {
+ return version, nil
}
}
- return "", fmt.Errorf("not found a version(<=%d) in versionList: %v", maxSdkVersion, versionList)
+ return "", fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion, versionList)
}
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
diff --git a/android/module.go b/android/module.go
index f5adc54..c4e43c2 100644
--- a/android/module.go
+++ b/android/module.go
@@ -625,7 +625,7 @@
Native_bridge_supported *bool `android:"arch_variant"`
// init.rc files to be installed if this module is installed
- Init_rc []string `android:"path"`
+ Init_rc []string `android:"arch_variant,path"`
// VINTF manifest fragments to be installed if this module is installed
Vintf_fragments []string `android:"path"`
diff --git a/android/sdk.go b/android/sdk.go
index 9ea7ff4..f2cdc88 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -237,9 +237,25 @@
// * string
// * array of the above
// * bool
+ // For these types it is an error if multiple properties with the same name
+ // are added.
+ //
+ // * pointer to a struct
// * BpPropertySet
//
- // It is an error if multiple properties with the same name are added.
+ // A pointer to a Blueprint-style property struct is first converted into a
+ // BpPropertySet by traversing the fields and adding their values as
+ // properties in a BpPropertySet. A field with a struct value is itself
+ // converted into a BpPropertySet before adding.
+ //
+ // Adding a BpPropertySet is done as follows:
+ // * If no property with the name exists then the BpPropertySet is added
+ // directly to this property. Care must be taken to ensure that it does not
+ // introduce a cycle.
+ // * If a property exists with the name and the current value is a
+ // BpPropertySet then every property of the new BpPropertySet is added to
+ // the existing BpPropertySet.
+ // * Otherwise, if a property exists with the name then it is an error.
AddProperty(name string, value interface{})
// Add a property with an associated tag
diff --git a/android/variable.go b/android/variable.go
index 53f081e..ce523ed 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -365,12 +365,12 @@
*v = productVariables{
BuildNumberFile: stringPtr("build_number.txt"),
- Platform_version_name: stringPtr("Q"),
- Platform_sdk_version: intPtr(28),
- Platform_sdk_codename: stringPtr("Q"),
+ Platform_version_name: stringPtr("S"),
+ Platform_sdk_version: intPtr(30),
+ Platform_sdk_codename: stringPtr("S"),
Platform_sdk_final: boolPtr(false),
- Platform_version_active_codenames: []string{"Q"},
- Platform_vndk_version: stringPtr("Q"),
+ Platform_version_active_codenames: []string{"S"},
+ Platform_vndk_version: stringPtr("S"),
HostArch: stringPtr("x86_64"),
HostSecondaryArch: stringPtr("x86"),
diff --git a/apex/androidmk.go b/apex/androidmk.go
index c4fe3a3..f76181d 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -135,7 +135,7 @@
}
}
if len(newDataPaths) > 0 {
- fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(cc.AndroidMkDataPaths(newDataPaths), " "))
+ fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(android.AndroidMkDataPaths(newDataPaths), " "))
}
if fi.module != nil && len(fi.module.NoticeFiles()) > 0 {
diff --git a/apex/apex.go b/apex/apex.go
index e8294a8..0b69111 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1499,6 +1499,12 @@
}
}
for i, target := range targets {
+ if target.HostCross {
+ // Don't include artifats for the host cross targets because there is no way
+ // for us to run those artifacts natively on host
+ continue
+ }
+
// When multilib.* is omitted for native_shared_libs/jni_libs/tests, it implies
// multilib.both
addDependenciesForNativeModules(ctx,
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 02689a0..2099109 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -836,6 +836,105 @@
})
}
+func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
+ t.Parallel()
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib", "mylib3"],
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2", "mylib3"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "28",
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ cflags: ["-include mylib.h"],
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["28", "29", "30", "current"],
+ },
+ min_sdk_version: "28",
+ }
+
+ cc_library {
+ name: "mylib3",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib4"],
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["28", "29", "30", "current"],
+ },
+ apex_available: [ "myapex" ],
+ min_sdk_version: "28",
+ }
+
+ cc_library {
+ name: "mylib4",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "28",
+ }
+ `)
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that direct non-stubs dep is always included
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+
+ // Ensure that indirect stubs dep is not included
+ ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+
+ // Ensure that direct stubs dep is included
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
+
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex29").Rule("ld").Args["libFlags"]
+
+ // Ensure that mylib is linking with the version 29 stubs for mylib2
+ ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_29/mylib2.so")
+ // ... and not linking to the non-stub (impl) variant of mylib2
+ 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_apex29/mylib3.so")
+ // .. and not linking to the stubs variant of mylib3
+ ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_29/mylib3.so")
+
+ // Ensure that stubs libs are built without -include flags
+ mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ ensureNotContains(t, mylib2Cflags, "-include ")
+
+ // Ensure that genstub is invoked with --apex
+ ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_29").Rule("genStubSrc").Args["flags"])
+
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "lib64/mylib.so",
+ "lib64/mylib3.so",
+ "lib64/mylib4.so",
+ })
+}
+
func TestApexWithExplicitStubsDependency(t *testing.T) {
ctx, _ := testApex(t, `
apex {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5bdbac6..4f149af 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -83,6 +83,13 @@
if len(c.Properties.Logtags) > 0 {
entries.AddStrings("LOCAL_LOGTAGS_FILES", c.Properties.Logtags...)
}
+ // Note: Pass the exact value of AndroidMkSystemSharedLibs to the Make
+ // world, even if it is an empty list. In the Make world,
+ // LOCAL_SYSTEM_SHARED_LIBRARIES defaults to "none", which is expanded
+ // to the default list of system shared libs by the build system.
+ // Soong computes the exact list of system shared libs, so we have to
+ // override the default value when the list of libs is actually empty.
+ entries.SetString("LOCAL_SYSTEM_SHARED_LIBRARIES", strings.Join(c.Properties.AndroidMkSystemSharedLibs, " "))
if len(c.Properties.AndroidMkSharedLibs) > 0 {
entries.AddStrings("LOCAL_SHARED_LIBRARIES", c.Properties.AndroidMkSharedLibs...)
}
@@ -149,24 +156,6 @@
return []android.AndroidMkEntries{entries}
}
-func AndroidMkDataPaths(data []android.DataPath) []string {
- var testFiles []string
- for _, d := range data {
- rel := d.SrcPath.Rel()
- path := d.SrcPath.String()
- if !strings.HasSuffix(path, rel) {
- panic(fmt.Errorf("path %q does not end with %q", path, rel))
- }
- path = strings.TrimSuffix(path, rel)
- testFileString := path + ":" + rel
- if len(d.RelativeInstallPath) > 0 {
- testFileString += ":" + d.RelativeInstallPath
- }
- testFiles = append(testFiles, testFileString)
- }
- return testFiles
-}
-
func androidMkWriteExtraTestConfigs(extraTestConfigs android.Paths, entries *android.AndroidMkEntries) {
if len(extraTestConfigs) > 0 {
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
@@ -176,7 +165,7 @@
}
func androidMkWriteTestData(data []android.DataPath, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- testFiles := AndroidMkDataPaths(data)
+ testFiles := android.AndroidMkDataPaths(data)
if len(testFiles) > 0 {
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
entries.AddStrings("LOCAL_TEST_DATA", testFiles...)
diff --git a/cc/builder.go b/cc/builder.go
index ef65348..81c09b1 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -221,7 +221,6 @@
ExecStrategy: "${config.REAbiDumperExecStrategy}",
Platform: map[string]string{
remoteexec.PoolKey: "${config.RECXXPool}",
- "InputRootAbsolutePath": android.AbsSrcDirForExistingUseCases(),
},
}, []string{"cFlags", "exportDirs"}, nil)
diff --git a/cc/cc.go b/cc/cc.go
index e71f859..a813428 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -100,6 +100,9 @@
// Used for data dependencies adjacent to tests
DataLibs []string
+ // Used by DepsMutator to pass system_shared_libs information to check_elf_file.py.
+ SystemSharedLibs []string
+
StaticUnwinderIfLegacy bool
ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string
@@ -238,6 +241,9 @@
PreventInstall bool `blueprint:"mutated"`
ApexesProvidingSharedLibs []string `blueprint:"mutated"`
+ // Set by DepsMutator.
+ AndroidMkSystemSharedLibs []string `blueprint:"mutated"`
+
ImageVariationPrefix string `blueprint:"mutated"`
VndkVersion string `blueprint:"mutated"`
SubName string `blueprint:"mutated"`
@@ -1839,6 +1845,8 @@
deps := c.deps(ctx)
+ c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
+
variantNdkLibs := []string{}
variantLateNdkLibs := []string{}
if ctx.Os() == android.Android {
@@ -2465,7 +2473,7 @@
// when to use (unspecified) stubs, check min_sdk_version and choose the right one
if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned {
- versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion.FinalOrFutureInt())
+ versionToUse, err := c.ChooseSdkVersion(ctx, ccDep.StubsVersions(), c.apexSdkVersion)
if err != nil {
ctx.OtherModuleErrorf(dep, err.Error())
return
@@ -2488,7 +2496,7 @@
// if this is for use_vendor apex && dep has stubsVersions
// apply the same rule of apex sdk enforcement to choose right version
var err error
- versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion.FinalOrFutureInt())
+ versionToUse, err = c.ChooseSdkVersion(ctx, versions, c.apexSdkVersion)
if err != nil {
ctx.OtherModuleErrorf(dep, err.Error())
return
@@ -2559,17 +2567,20 @@
// in the context of proper cc.Modules.
if ccWholeStaticLib, ok := ccDep.(*Module); ok {
staticLib := ccWholeStaticLib.linker.(libraryInterface)
- if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil {
- postfix := " (required by " + ctx.OtherModuleName(dep) + ")"
- for i := range missingDeps {
- missingDeps[i] += postfix
- }
- ctx.AddMissingDependencies(missingDeps)
- }
- if _, ok := ccWholeStaticLib.linker.(prebuiltLinkerInterface); ok {
- depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
+ if objs := staticLib.objs(); len(objs.objFiles) > 0 {
+ depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(objs)
} else {
- depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs())
+ // This case normally catches prebuilt static
+ // libraries, but it can also occur when
+ // AllowMissingDependencies is on and the
+ // dependencies has no sources of its own
+ // but has a whole_static_libs dependency
+ // on a missing library. We want to depend
+ // on the .a file so that there is something
+ // in the dependency tree that contains the
+ // error rule for the missing transitive
+ // dependency.
+ depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
}
} else {
ctx.ModuleErrorf(
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 132d091..e0d4640 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3780,3 +3780,46 @@
t.Errorf("expected -DBAR in cppflags, got %q", libfoo.flags.Local.CppFlags)
}
}
+
+func TestEmptyWholeStaticLibsAllowMissingDependencies(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_static {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ whole_static_libs: ["libbar"],
+ }
+
+ cc_library_static {
+ name: "libbar",
+ whole_static_libs: ["libmissing"],
+ }
+ `
+
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.Allow_missing_dependencies = BoolPtr(true)
+
+ ctx := CreateTestContext()
+ ctx.SetAllowMissingDependencies(true)
+ ctx.Register(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Output("libbar.a")
+ if g, w := libbar.Rule, android.ErrorRule; g != w {
+ t.Fatalf("Expected libbar rule to be %q, got %q", w, g)
+ }
+
+ if g, w := libbar.Args["error"], "missing dependencies: libmissing"; !strings.Contains(g, w) {
+ t.Errorf("Expected libbar error to contain %q, was %q", w, g)
+ }
+
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Output("libfoo.a")
+ if g, w := libfoo.Inputs.Strings(), libbar.Output.String(); !android.InList(w, g) {
+ t.Errorf("Expected libfoo.a to depend on %q, got %q", w, g)
+ }
+
+}
diff --git a/cc/check.go b/cc/check.go
index 46328e9..0058b8c 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -38,6 +38,8 @@
ctx.PropertyErrorf(prop, "Illegal flag `%s`", flag)
} else if flag == "--coverage" {
ctx.PropertyErrorf(prop, "Bad flag: `%s`, use native_coverage instead", flag)
+ } else if flag == "-fwhole-program-vtables" {
+ ctx.PropertyErrorf(prop, "Bad flag: `%s`, use whole_program_vtables instead", flag)
} else if flag == "-Weverything" {
if !ctx.Config().IsEnvTrue("ANDROID_TEMPORARILY_ALLOW_WEVERYTHING") {
ctx.PropertyErrorf(prop, "-Weverything is not allowed in Android.bp files. "+
diff --git a/cc/library.go b/cc/library.go
index 8048f00..bf7868f 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -338,10 +338,6 @@
flagExporter
stripper Stripper
- // If we're used as a whole_static_lib, our missing dependencies need
- // to be given
- wholeStaticMissingDeps []string
-
// For whole_static_libs
objects Objects
@@ -682,7 +678,6 @@
}
type libraryInterface interface {
- getWholeStaticMissingDeps() []string
static() bool
shared() bool
objs() Objects
@@ -889,8 +884,6 @@
library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
- library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
-
ctx.CheckbuildFile(outputFile)
return outputFile
@@ -1182,10 +1175,6 @@
BoolDefault(library.SharedProperties.Shared.Enabled, true)
}
-func (library *libraryDecorator) getWholeStaticMissingDeps() []string {
- return append([]string(nil), library.wholeStaticMissingDeps...)
-}
-
func (library *libraryDecorator) objs() Objects {
return library.objects
}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 2f15544..41ce294 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -221,10 +221,7 @@
// Add properties that may, or may not, be arch specific.
func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo *nativeLibInfoProperties, outputProperties android.BpPropertySet) {
- if libInfo.SanitizeNever {
- sanitizeSet := outputProperties.AddPropertySet("sanitize")
- sanitizeSet.AddProperty("never", true)
- }
+ outputProperties.AddProperty("sanitize", &libInfo.Sanitize)
// Copy the generated library to the snapshot and add a reference to it in the .bp module.
if libInfo.outputFile != nil {
@@ -295,9 +292,9 @@
outputProperties.AddProperty(property, includeDirs[property])
}
- if len(libInfo.StubsVersion) > 0 {
+ if len(libInfo.StubsVersions) > 0 {
stubsSet := outputProperties.AddPropertySet("stubs")
- stubsSet.AddProperty("versions", []string{libInfo.StubsVersion})
+ stubsSet.AddProperty("versions", libInfo.StubsVersions)
}
}
@@ -368,13 +365,15 @@
// The specific stubs version for the lib variant, or empty string if stubs
// are not in use.
//
- // Marked 'ignored-on-host' as the StubsVersion() from which this is initialized is
- // not set on host and the stubs.versions property which this is written to is does
- // not vary by arch so cannot be android specific.
- StubsVersion string `sdk:"ignored-on-host"`
+ // Marked 'ignored-on-host' as the AllStubsVersions() from which this is
+ // initialized is not set on host and the stubs.versions property which this
+ // is written to does not vary by arch so cannot be android specific.
+ StubsVersions []string `sdk:"ignored-on-host"`
- // Value of SanitizeProperties.Sanitize.Never. Needs to be propagated for CRT objects.
- SanitizeNever bool `android:"arch_variant"`
+ // Value of SanitizeProperties.Sanitize. Several - but not all - of these
+ // affect the expanded variants. All are propagated to avoid entangling the
+ // sanitizer logic with the snapshot generation.
+ Sanitize SanitizeUserProps `android:"arch_variant"`
// outputFile is not exported as it is always arch specific.
outputFile android.Path
@@ -420,11 +419,15 @@
p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
if ccModule.HasStubsVariants() {
- p.StubsVersion = ccModule.StubsVersion()
+ // TODO(b/169373910): 1. Only output the specific version (from
+ // ccModule.StubsVersion()) if the module is versioned. 2. Ensure that all
+ // the versioned stub libs are retained in the prebuilt tree; currently only
+ // the stub corresponding to ccModule.StubsVersion() is.
+ p.StubsVersions = ccModule.AllStubsVersions()
}
- if ccModule.sanitize != nil && proptools.Bool(ccModule.sanitize.Properties.Sanitize.Never) {
- p.SanitizeNever = true
+ if ccModule.sanitize != nil {
+ p.Sanitize = ccModule.sanitize.Properties.Sanitize
}
}
diff --git a/cc/linker.go b/cc/linker.go
index 58f8a29..12c8b2c 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -278,19 +278,19 @@
deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
}
- systemSharedLibs := linker.Properties.System_shared_libs
- if systemSharedLibs == nil {
+ deps.SystemSharedLibs = linker.Properties.System_shared_libs
+ if deps.SystemSharedLibs == nil {
// Provide a default system_shared_libs if it is unspecified. Note: If an
// empty list [] is specified, it implies that the module declines the
// default system_shared_libs.
- systemSharedLibs = []string{"libc", "libm", "libdl"}
+ deps.SystemSharedLibs = []string{"libc", "libm", "libdl"}
}
if inList("libdl", deps.SharedLibs) {
// If system_shared_libs has libc but not libdl, make sure shared_libs does not
// have libdl to avoid loading libdl before libc.
- if inList("libc", systemSharedLibs) {
- if !inList("libdl", systemSharedLibs) {
+ if inList("libc", deps.SystemSharedLibs) {
+ if !inList("libdl", deps.SystemSharedLibs) {
ctx.PropertyErrorf("shared_libs",
"libdl must be in system_shared_libs, not shared_libs")
}
@@ -300,12 +300,12 @@
// If libc and libdl are both in system_shared_libs make sure libdl comes after libc
// to avoid loading libdl before libc.
- if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
- indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
+ if inList("libdl", deps.SystemSharedLibs) && inList("libc", deps.SystemSharedLibs) &&
+ indexList("libdl", deps.SystemSharedLibs) < indexList("libc", deps.SystemSharedLibs) {
ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
}
- deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
+ deps.LateSharedLibs = append(deps.LateSharedLibs, deps.SystemSharedLibs...)
}
if ctx.Fuchsia() {
diff --git a/cc/lto.go b/cc/lto.go
index 3e1acdf..abd8dfb 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -45,8 +45,6 @@
Thin *bool `android:"arch_variant"`
} `android:"arch_variant"`
- GlobalThin *bool `blueprint:"mutated"`
-
// Dep properties indicate that this module needs to be built with LTO
// since it is an object dependency of an LTO module.
FullDep bool `blueprint:"mutated"`
@@ -71,7 +69,13 @@
if ctx.Config().IsEnvTrue("DISABLE_LTO") {
lto.Properties.Lto.Never = boolPtr(true)
} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
- lto.Properties.GlobalThin = boolPtr(true)
+ staticLib := ctx.static() && !ctx.staticBinary()
+ hostBin := ctx.Host()
+ if !staticLib && !hostBin {
+ if !lto.Never() && !lto.FullLTO() {
+ lto.Properties.Lto.Thin = boolPtr(true)
+ }
+ }
}
}
@@ -133,7 +137,7 @@
// Can be called with a null receiver
func (lto *lto) LTO() bool {
- if lto == nil || lto.Disabled() {
+ if lto == nil || lto.Never() {
return false
}
@@ -145,18 +149,12 @@
}
func (lto *lto) ThinLTO() bool {
- if Bool(lto.Properties.GlobalThin) {
- if !lto.Disabled() && !lto.FullLTO() {
- return true
- }
- }
-
return Bool(lto.Properties.Lto.Thin)
}
// Is lto.never explicitly set to true?
-func (lto *lto) Disabled() bool {
- return lto.Properties.Lto.Never != nil && *lto.Properties.Lto.Never
+func (lto *lto) Never() bool {
+ return Bool(lto.Properties.Lto.Never)
}
// Propagate lto requirements down from binaries
@@ -184,7 +182,7 @@
}
if dep, ok := dep.(*Module); ok && dep.lto != nil &&
- !dep.lto.Disabled() {
+ !dep.lto.Never() {
if full && !dep.lto.FullLTO() {
dep.lto.Properties.FullDep = true
}
diff --git a/cc/ndkstubgen/__init__.py b/cc/ndkstubgen/__init__.py
index 2f4326a..86bf6ff 100755
--- a/cc/ndkstubgen/__init__.py
+++ b/cc/ndkstubgen/__init__.py
@@ -20,13 +20,16 @@
import logging
import os
import sys
+from typing import Iterable, TextIO
import symbolfile
+from symbolfile import Arch, Version
class Generator:
"""Output generator that writes stub source files and version scripts."""
- def __init__(self, src_file, version_script, arch, api, llndk, apex):
+ def __init__(self, src_file: TextIO, version_script: TextIO, arch: Arch,
+ api: int, llndk: bool, apex: bool) -> None:
self.src_file = src_file
self.version_script = version_script
self.arch = arch
@@ -34,12 +37,12 @@
self.llndk = llndk
self.apex = apex
- def write(self, versions):
+ def write(self, versions: Iterable[Version]) -> None:
"""Writes all symbol data to the output files."""
for version in versions:
self.write_version(version)
- def write_version(self, version):
+ def write_version(self, version: Version) -> None:
"""Writes a single version block's data to the output files."""
if symbolfile.should_omit_version(version, self.arch, self.api,
self.llndk, self.apex):
@@ -84,7 +87,7 @@
self.version_script.write('}' + base + ';\n')
-def parse_args():
+def parse_args() -> argparse.Namespace:
"""Parses and returns command line arguments."""
parser = argparse.ArgumentParser()
@@ -100,23 +103,31 @@
parser.add_argument(
'--apex', action='store_true', help='Use the APEX variant.')
+ # https://github.com/python/mypy/issues/1317
+ # mypy has issues with using os.path.realpath as an argument here.
parser.add_argument(
- '--api-map', type=os.path.realpath, required=True,
+ '--api-map',
+ type=os.path.realpath, # type: ignore
+ required=True,
help='Path to the API level map JSON file.')
parser.add_argument(
- 'symbol_file', type=os.path.realpath, help='Path to symbol file.')
+ 'symbol_file',
+ type=os.path.realpath, # type: ignore
+ help='Path to symbol file.')
parser.add_argument(
- 'stub_src', type=os.path.realpath,
+ 'stub_src',
+ type=os.path.realpath, # type: ignore
help='Path to output stub source file.')
parser.add_argument(
- 'version_script', type=os.path.realpath,
+ 'version_script',
+ type=os.path.realpath, # type: ignore
help='Path to output version script.')
return parser.parse_args()
-def main():
+def main() -> None:
"""Program entry point."""
args = parse_args()
diff --git a/cc/ndkstubgen/mypy.ini b/cc/ndkstubgen/mypy.ini
new file mode 100644
index 0000000..82aa7eb
--- /dev/null
+++ b/cc/ndkstubgen/mypy.ini
@@ -0,0 +1,2 @@
+[mypy]
+disallow_untyped_defs = True
diff --git a/cc/ndkstubgen/test_ndkstubgen.py b/cc/ndkstubgen/test_ndkstubgen.py
index 70bcf78..6d2c9d6 100755
--- a/cc/ndkstubgen/test_ndkstubgen.py
+++ b/cc/ndkstubgen/test_ndkstubgen.py
@@ -21,19 +21,20 @@
import ndkstubgen
import symbolfile
+from symbolfile import Arch, Tag
# pylint: disable=missing-docstring
class GeneratorTest(unittest.TestCase):
- def test_omit_version(self):
+ def test_omit_version(self) -> None:
# Thorough testing of the cases involved here is handled by
# OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9,
- False, False)
+ generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
+ 9, False, False)
version = symbolfile.Version('VERSION_PRIVATE', None, [], [
symbolfile.Symbol('foo', []),
@@ -42,74 +43,75 @@
self.assertEqual('', src_file.getvalue())
self.assertEqual('', version_file.getvalue())
- version = symbolfile.Version('VERSION', None, ['x86'], [
+ version = symbolfile.Version('VERSION', None, [Tag('x86')], [
symbolfile.Symbol('foo', []),
])
generator.write_version(version)
self.assertEqual('', src_file.getvalue())
self.assertEqual('', version_file.getvalue())
- version = symbolfile.Version('VERSION', None, ['introduced=14'], [
+ version = symbolfile.Version('VERSION', None, [Tag('introduced=14')], [
symbolfile.Symbol('foo', []),
])
generator.write_version(version)
self.assertEqual('', src_file.getvalue())
self.assertEqual('', version_file.getvalue())
- def test_omit_symbol(self):
+ def test_omit_symbol(self) -> None:
# Thorough testing of the cases involved here is handled by
# SymbolPresenceTest.
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9,
- False, False)
+ generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
+ 9, False, False)
version = symbolfile.Version('VERSION_1', None, [], [
- symbolfile.Symbol('foo', ['x86']),
+ symbolfile.Symbol('foo', [Tag('x86')]),
])
generator.write_version(version)
self.assertEqual('', src_file.getvalue())
self.assertEqual('', version_file.getvalue())
version = symbolfile.Version('VERSION_1', None, [], [
- symbolfile.Symbol('foo', ['introduced=14']),
+ symbolfile.Symbol('foo', [Tag('introduced=14')]),
])
generator.write_version(version)
self.assertEqual('', src_file.getvalue())
self.assertEqual('', version_file.getvalue())
version = symbolfile.Version('VERSION_1', None, [], [
- symbolfile.Symbol('foo', ['llndk']),
+ symbolfile.Symbol('foo', [Tag('llndk')]),
])
generator.write_version(version)
self.assertEqual('', src_file.getvalue())
self.assertEqual('', version_file.getvalue())
version = symbolfile.Version('VERSION_1', None, [], [
- symbolfile.Symbol('foo', ['apex']),
+ symbolfile.Symbol('foo', [Tag('apex')]),
])
generator.write_version(version)
self.assertEqual('', src_file.getvalue())
self.assertEqual('', version_file.getvalue())
- def test_write(self):
+ def test_write(self) -> None:
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9,
- False, False)
+ generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
+ 9, False, False)
versions = [
symbolfile.Version('VERSION_1', None, [], [
symbolfile.Symbol('foo', []),
- symbolfile.Symbol('bar', ['var']),
- symbolfile.Symbol('woodly', ['weak']),
- symbolfile.Symbol('doodly', ['weak', 'var']),
+ symbolfile.Symbol('bar', [Tag('var')]),
+ symbolfile.Symbol('woodly', [Tag('weak')]),
+ symbolfile.Symbol('doodly',
+ [Tag('weak'), Tag('var')]),
]),
symbolfile.Version('VERSION_2', 'VERSION_1', [], [
symbolfile.Symbol('baz', []),
]),
symbolfile.Version('VERSION_3', 'VERSION_1', [], [
- symbolfile.Symbol('qux', ['versioned=14']),
+ symbolfile.Symbol('qux', [Tag('versioned=14')]),
]),
]
@@ -141,7 +143,7 @@
class IntegrationTest(unittest.TestCase):
- def test_integration(self):
+ def test_integration(self) -> None:
api_map = {
'O': 9000,
'P': 9001,
@@ -178,14 +180,14 @@
wobble;
} VERSION_4;
"""))
- parser = symbolfile.SymbolFileParser(input_file, api_map, 'arm', 9,
- False, False)
+ parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
+ 9, False, False)
versions = parser.parse()
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9,
- False, False)
+ generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
+ 9, False, False)
generator.write(versions)
expected_src = textwrap.dedent("""\
@@ -213,7 +215,7 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
- def test_integration_future_api(self):
+ def test_integration_future_api(self) -> None:
api_map = {
'O': 9000,
'P': 9001,
@@ -230,14 +232,14 @@
*;
};
"""))
- parser = symbolfile.SymbolFileParser(input_file, api_map, 'arm', 9001,
- False, False)
+ parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
+ 9001, False, False)
versions = parser.parse()
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9001,
- False, False)
+ generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
+ 9001, False, False)
generator.write(versions)
expected_src = textwrap.dedent("""\
@@ -255,7 +257,7 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
- def test_multiple_definition(self):
+ def test_multiple_definition(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
global:
@@ -280,8 +282,8 @@
} VERSION_2;
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False,
- False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
with self.assertRaises(
symbolfile.MultiplyDefinedSymbolError) as ex_context:
@@ -289,7 +291,7 @@
self.assertEqual(['bar', 'foo'],
ex_context.exception.multiply_defined_symbols)
- def test_integration_with_apex(self):
+ def test_integration_with_apex(self) -> None:
api_map = {
'O': 9000,
'P': 9001,
@@ -328,14 +330,14 @@
wobble;
} VERSION_4;
"""))
- parser = symbolfile.SymbolFileParser(input_file, api_map, 'arm', 9,
- False, True)
+ parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
+ 9, False, True)
versions = parser.parse()
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, 'arm', 9,
- False, True)
+ generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
+ 9, False, True)
generator.write(versions)
expected_src = textwrap.dedent("""\
@@ -369,7 +371,8 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
-def main():
+
+def main() -> None:
suite = unittest.TestLoader().loadTestsFromName(__name__)
unittest.TextTestRunner(verbosity=3).run(suite)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 174dcfe..8c3e97a 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -139,56 +139,59 @@
return t == asan || t == fuzzer || t == hwasan
}
-type SanitizeProperties struct {
- // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
- Sanitize struct {
- Never *bool `android:"arch_variant"`
+type SanitizeUserProps struct {
+ Never *bool `android:"arch_variant"`
- // main sanitizers
- Address *bool `android:"arch_variant"`
- Thread *bool `android:"arch_variant"`
- Hwaddress *bool `android:"arch_variant"`
+ // main sanitizers
+ Address *bool `android:"arch_variant"`
+ Thread *bool `android:"arch_variant"`
+ Hwaddress *bool `android:"arch_variant"`
- // local sanitizers
+ // local sanitizers
+ Undefined *bool `android:"arch_variant"`
+ All_undefined *bool `android:"arch_variant"`
+ Misc_undefined []string `android:"arch_variant"`
+ Fuzzer *bool `android:"arch_variant"`
+ Safestack *bool `android:"arch_variant"`
+ Cfi *bool `android:"arch_variant"`
+ Integer_overflow *bool `android:"arch_variant"`
+ Scudo *bool `android:"arch_variant"`
+ Scs *bool `android:"arch_variant"`
+
+ // A modifier for ASAN and HWASAN for write only instrumentation
+ Writeonly *bool `android:"arch_variant"`
+
+ // Sanitizers to run in the diagnostic mode (as opposed to the release mode).
+ // Replaces abort() on error with a human-readable error message.
+ // Address and Thread sanitizers always run in diagnostic mode.
+ Diag struct {
Undefined *bool `android:"arch_variant"`
- All_undefined *bool `android:"arch_variant"`
- Misc_undefined []string `android:"arch_variant"`
- Fuzzer *bool `android:"arch_variant"`
- Safestack *bool `android:"arch_variant"`
Cfi *bool `android:"arch_variant"`
Integer_overflow *bool `android:"arch_variant"`
- Scudo *bool `android:"arch_variant"`
- Scs *bool `android:"arch_variant"`
+ Misc_undefined []string `android:"arch_variant"`
+ No_recover []string
+ }
- // A modifier for ASAN and HWASAN for write only instrumentation
- Writeonly *bool `android:"arch_variant"`
+ // value to pass to -fsanitize-recover=
+ Recover []string
- // Sanitizers to run in the diagnostic mode (as opposed to the release mode).
- // Replaces abort() on error with a human-readable error message.
- // Address and Thread sanitizers always run in diagnostic mode.
- Diag struct {
- Undefined *bool `android:"arch_variant"`
- Cfi *bool `android:"arch_variant"`
- Integer_overflow *bool `android:"arch_variant"`
- Misc_undefined []string `android:"arch_variant"`
- No_recover []string
- }
+ // value to pass to -fsanitize-blacklist
+ Blocklist *string
+}
- // value to pass to -fsanitize-recover=
- Recover []string
-
- // value to pass to -fsanitize-blacklist
- Blocklist *string
- } `android:"arch_variant"`
-
- SanitizerEnabled bool `blueprint:"mutated"`
- SanitizeDep bool `blueprint:"mutated"`
- MinimalRuntimeDep bool `blueprint:"mutated"`
- BuiltinsDep bool `blueprint:"mutated"`
- UbsanRuntimeDep bool `blueprint:"mutated"`
- InSanitizerDir bool `blueprint:"mutated"`
- Sanitizers []string `blueprint:"mutated"`
- DiagSanitizers []string `blueprint:"mutated"`
+type SanitizeProperties struct {
+ // Enable AddressSanitizer, ThreadSanitizer, UndefinedBehaviorSanitizer, and
+ // others. Please see SanitizerUserProps in build/soong/cc/sanitize.go for
+ // details.
+ Sanitize SanitizeUserProps `android:"arch_variant"`
+ SanitizerEnabled bool `blueprint:"mutated"`
+ SanitizeDep bool `blueprint:"mutated"`
+ MinimalRuntimeDep bool `blueprint:"mutated"`
+ BuiltinsDep bool `blueprint:"mutated"`
+ UbsanRuntimeDep bool `blueprint:"mutated"`
+ InSanitizerDir bool `blueprint:"mutated"`
+ Sanitizers []string `blueprint:"mutated"`
+ DiagSanitizers []string `blueprint:"mutated"`
}
type sanitize struct {
diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py
index faa3823..5678e7d 100644
--- a/cc/symbolfile/__init__.py
+++ b/cc/symbolfile/__init__.py
@@ -14,15 +14,31 @@
# limitations under the License.
#
"""Parser for Android's version script information."""
+from dataclasses import dataclass
import logging
import re
+from typing import (
+ Dict,
+ Iterable,
+ List,
+ Mapping,
+ NewType,
+ Optional,
+ TextIO,
+ Tuple,
+)
+
+
+ApiMap = Mapping[str, int]
+Arch = NewType('Arch', str)
+Tag = NewType('Tag', str)
ALL_ARCHITECTURES = (
- 'arm',
- 'arm64',
- 'x86',
- 'x86_64',
+ Arch('arm'),
+ Arch('arm64'),
+ Arch('x86'),
+ Arch('x86_64'),
)
@@ -30,18 +46,36 @@
FUTURE_API_LEVEL = 10000
-def logger():
+def logger() -> logging.Logger:
"""Return the main logger for this module."""
return logging.getLogger(__name__)
-def get_tags(line):
+@dataclass
+class Symbol:
+ """A symbol definition from a symbol file."""
+
+ name: str
+ tags: List[Tag]
+
+
+@dataclass
+class Version:
+ """A version block of a symbol file."""
+
+ name: str
+ base: Optional[str]
+ tags: List[Tag]
+ symbols: List[Symbol]
+
+
+def get_tags(line: str) -> List[Tag]:
"""Returns a list of all tags on this line."""
_, _, all_tags = line.strip().partition('#')
- return [e for e in re.split(r'\s+', all_tags) if e.strip()]
+ return [Tag(e) for e in re.split(r'\s+', all_tags) if e.strip()]
-def is_api_level_tag(tag):
+def is_api_level_tag(tag: Tag) -> bool:
"""Returns true if this tag has an API level that may need decoding."""
if tag.startswith('introduced='):
return True
@@ -52,7 +86,7 @@
return False
-def decode_api_level(api, api_map):
+def decode_api_level(api: str, api_map: ApiMap) -> int:
"""Decodes the API level argument into the API level number.
For the average case, this just decodes the integer value from the string,
@@ -70,12 +104,13 @@
return api_map[api]
-def decode_api_level_tags(tags, api_map):
+def decode_api_level_tags(tags: Iterable[Tag], api_map: ApiMap) -> List[Tag]:
"""Decodes API level code names in a list of tags.
Raises:
ParseError: An unknown version name was found in a tag.
"""
+ decoded_tags = list(tags)
for idx, tag in enumerate(tags):
if not is_api_level_tag(tag):
continue
@@ -83,13 +118,13 @@
try:
decoded = str(decode_api_level(value, api_map))
- tags[idx] = '='.join([name, decoded])
+ decoded_tags[idx] = Tag('='.join([name, decoded]))
except KeyError:
- raise ParseError('Unknown version name in tag: {}'.format(tag))
- return tags
+ raise ParseError(f'Unknown version name in tag: {tag}')
+ return decoded_tags
-def split_tag(tag):
+def split_tag(tag: Tag) -> Tuple[str, str]:
"""Returns a key/value tuple of the tag.
Raises:
@@ -103,7 +138,7 @@
return key, value
-def get_tag_value(tag):
+def get_tag_value(tag: Tag) -> str:
"""Returns the value of a key/value tag.
Raises:
@@ -114,12 +149,13 @@
return split_tag(tag)[1]
-def version_is_private(version):
+def version_is_private(version: str) -> bool:
"""Returns True if the version name should be treated as private."""
return version.endswith('_PRIVATE') or version.endswith('_PLATFORM')
-def should_omit_version(version, arch, api, llndk, apex):
+def should_omit_version(version: Version, arch: Arch, api: int, llndk: bool,
+ apex: bool) -> bool:
"""Returns True if the version section should be ommitted.
We want to omit any sections that do not have any symbols we'll have in the
@@ -145,7 +181,8 @@
return False
-def should_omit_symbol(symbol, arch, api, llndk, apex):
+def should_omit_symbol(symbol: Symbol, arch: Arch, api: int, llndk: bool,
+ apex: bool) -> bool:
"""Returns True if the symbol should be omitted."""
no_llndk_no_apex = 'llndk' not in symbol.tags and 'apex' not in symbol.tags
keep = no_llndk_no_apex or \
@@ -160,7 +197,7 @@
return False
-def symbol_in_arch(tags, arch):
+def symbol_in_arch(tags: Iterable[Tag], arch: Arch) -> bool:
"""Returns true if the symbol is present for the given architecture."""
has_arch_tags = False
for tag in tags:
@@ -175,7 +212,7 @@
return not has_arch_tags
-def symbol_in_api(tags, arch, api):
+def symbol_in_api(tags: Iterable[Tag], arch: Arch, api: int) -> bool:
"""Returns true if the symbol is present for the given API level."""
introduced_tag = None
arch_specific = False
@@ -197,7 +234,7 @@
return api >= int(get_tag_value(introduced_tag))
-def symbol_versioned_in_api(tags, api):
+def symbol_versioned_in_api(tags: Iterable[Tag], api: int) -> bool:
"""Returns true if the symbol should be versioned for the given API.
This models the `versioned=API` tag. This should be a very uncommonly
@@ -223,68 +260,40 @@
class MultiplyDefinedSymbolError(RuntimeError):
"""A symbol name was multiply defined."""
- def __init__(self, multiply_defined_symbols):
- super(MultiplyDefinedSymbolError, self).__init__(
+ def __init__(self, multiply_defined_symbols: Iterable[str]) -> None:
+ super().__init__(
'Version script contains multiple definitions for: {}'.format(
', '.join(multiply_defined_symbols)))
self.multiply_defined_symbols = multiply_defined_symbols
-class Version:
- """A version block of a symbol file."""
- def __init__(self, name, base, tags, symbols):
- self.name = name
- self.base = base
- self.tags = tags
- self.symbols = symbols
-
- def __eq__(self, other):
- if self.name != other.name:
- return False
- if self.base != other.base:
- return False
- if self.tags != other.tags:
- return False
- if self.symbols != other.symbols:
- return False
- return True
-
-
-class Symbol:
- """A symbol definition from a symbol file."""
- def __init__(self, name, tags):
- self.name = name
- self.tags = tags
-
- def __eq__(self, other):
- return self.name == other.name and set(self.tags) == set(other.tags)
-
-
class SymbolFileParser:
"""Parses NDK symbol files."""
- def __init__(self, input_file, api_map, arch, api, llndk, apex):
+ def __init__(self, input_file: TextIO, api_map: ApiMap, arch: Arch,
+ api: int, llndk: bool, apex: bool) -> None:
self.input_file = input_file
self.api_map = api_map
self.arch = arch
self.api = api
self.llndk = llndk
self.apex = apex
- self.current_line = None
+ self.current_line: Optional[str] = None
- def parse(self):
+ def parse(self) -> List[Version]:
"""Parses the symbol file and returns a list of Version objects."""
versions = []
while self.next_line() != '':
+ assert self.current_line is not None
if '{' in self.current_line:
versions.append(self.parse_version())
else:
raise ParseError(
- 'Unexpected contents at top level: ' + self.current_line)
+ f'Unexpected contents at top level: {self.current_line}')
self.check_no_duplicate_symbols(versions)
return versions
- def check_no_duplicate_symbols(self, versions):
+ def check_no_duplicate_symbols(self, versions: Iterable[Version]) -> None:
"""Raises errors for multiply defined symbols.
This situation is the normal case when symbol versioning is actually
@@ -312,12 +321,13 @@
raise MultiplyDefinedSymbolError(
sorted(list(multiply_defined_symbols)))
- def parse_version(self):
+ def parse_version(self) -> Version:
"""Parses a single version section and returns a Version object."""
+ assert self.current_line is not None
name = self.current_line.split('{')[0].strip()
tags = get_tags(self.current_line)
tags = decode_api_level_tags(tags, self.api_map)
- symbols = []
+ symbols: List[Symbol] = []
global_scope = True
cpp_symbols = False
while self.next_line() != '':
@@ -333,9 +343,7 @@
cpp_symbols = False
else:
base = base.rstrip(';').rstrip()
- if base == '':
- base = None
- return Version(name, base, tags, symbols)
+ return Version(name, base or None, tags, symbols)
elif 'extern "C++" {' in self.current_line:
cpp_symbols = True
elif not cpp_symbols and ':' in self.current_line:
@@ -354,8 +362,9 @@
pass
raise ParseError('Unexpected EOF in version block.')
- def parse_symbol(self):
+ def parse_symbol(self) -> Symbol:
"""Parses a single symbol line and returns a Symbol object."""
+ assert self.current_line is not None
if ';' not in self.current_line:
raise ParseError(
'Expected ; to terminate symbol: ' + self.current_line)
@@ -368,7 +377,7 @@
tags = decode_api_level_tags(tags, self.api_map)
return Symbol(name, tags)
- def next_line(self):
+ def next_line(self) -> str:
"""Returns the next non-empty non-comment line.
A return value of '' indicates EOF.
diff --git a/cc/symbolfile/mypy.ini b/cc/symbolfile/mypy.ini
new file mode 100644
index 0000000..82aa7eb
--- /dev/null
+++ b/cc/symbolfile/mypy.ini
@@ -0,0 +1,2 @@
+[mypy]
+disallow_untyped_defs = True
diff --git a/cc/symbolfile/test_symbolfile.py b/cc/symbolfile/test_symbolfile.py
index c91131f..92b1399 100644
--- a/cc/symbolfile/test_symbolfile.py
+++ b/cc/symbolfile/test_symbolfile.py
@@ -19,12 +19,13 @@
import unittest
import symbolfile
+from symbolfile import Arch, Tag
# pylint: disable=missing-docstring
class DecodeApiLevelTest(unittest.TestCase):
- def test_decode_api_level(self):
+ def test_decode_api_level(self) -> None:
self.assertEqual(9, symbolfile.decode_api_level('9', {}))
self.assertEqual(9000, symbolfile.decode_api_level('O', {'O': 9000}))
@@ -33,70 +34,73 @@
class TagsTest(unittest.TestCase):
- def test_get_tags_no_tags(self):
+ def test_get_tags_no_tags(self) -> None:
self.assertEqual([], symbolfile.get_tags(''))
self.assertEqual([], symbolfile.get_tags('foo bar baz'))
- def test_get_tags(self):
+ def test_get_tags(self) -> None:
self.assertEqual(['foo', 'bar'], symbolfile.get_tags('# foo bar'))
self.assertEqual(['bar', 'baz'], symbolfile.get_tags('foo # bar baz'))
- def test_split_tag(self):
- self.assertTupleEqual(('foo', 'bar'), symbolfile.split_tag('foo=bar'))
- self.assertTupleEqual(('foo', 'bar=baz'), symbolfile.split_tag('foo=bar=baz'))
+ def test_split_tag(self) -> None:
+ self.assertTupleEqual(('foo', 'bar'),
+ symbolfile.split_tag(Tag('foo=bar')))
+ self.assertTupleEqual(('foo', 'bar=baz'),
+ symbolfile.split_tag(Tag('foo=bar=baz')))
with self.assertRaises(ValueError):
- symbolfile.split_tag('foo')
+ symbolfile.split_tag(Tag('foo'))
- def test_get_tag_value(self):
- self.assertEqual('bar', symbolfile.get_tag_value('foo=bar'))
- self.assertEqual('bar=baz', symbolfile.get_tag_value('foo=bar=baz'))
+ def test_get_tag_value(self) -> None:
+ self.assertEqual('bar', symbolfile.get_tag_value(Tag('foo=bar')))
+ self.assertEqual('bar=baz',
+ symbolfile.get_tag_value(Tag('foo=bar=baz')))
with self.assertRaises(ValueError):
- symbolfile.get_tag_value('foo')
+ symbolfile.get_tag_value(Tag('foo'))
- def test_is_api_level_tag(self):
- self.assertTrue(symbolfile.is_api_level_tag('introduced=24'))
- self.assertTrue(symbolfile.is_api_level_tag('introduced-arm=24'))
- self.assertTrue(symbolfile.is_api_level_tag('versioned=24'))
+ def test_is_api_level_tag(self) -> None:
+ self.assertTrue(symbolfile.is_api_level_tag(Tag('introduced=24')))
+ self.assertTrue(symbolfile.is_api_level_tag(Tag('introduced-arm=24')))
+ self.assertTrue(symbolfile.is_api_level_tag(Tag('versioned=24')))
# Shouldn't try to process things that aren't a key/value tag.
- self.assertFalse(symbolfile.is_api_level_tag('arm'))
- self.assertFalse(symbolfile.is_api_level_tag('introduced'))
- self.assertFalse(symbolfile.is_api_level_tag('versioned'))
+ self.assertFalse(symbolfile.is_api_level_tag(Tag('arm')))
+ self.assertFalse(symbolfile.is_api_level_tag(Tag('introduced')))
+ self.assertFalse(symbolfile.is_api_level_tag(Tag('versioned')))
# We don't support arch specific `versioned` tags.
- self.assertFalse(symbolfile.is_api_level_tag('versioned-arm=24'))
+ self.assertFalse(symbolfile.is_api_level_tag(Tag('versioned-arm=24')))
- def test_decode_api_level_tags(self):
+ def test_decode_api_level_tags(self) -> None:
api_map = {
'O': 9000,
'P': 9001,
}
tags = [
- 'introduced=9',
- 'introduced-arm=14',
- 'versioned=16',
- 'arm',
- 'introduced=O',
- 'introduced=P',
+ Tag('introduced=9'),
+ Tag('introduced-arm=14'),
+ Tag('versioned=16'),
+ Tag('arm'),
+ Tag('introduced=O'),
+ Tag('introduced=P'),
]
expected_tags = [
- 'introduced=9',
- 'introduced-arm=14',
- 'versioned=16',
- 'arm',
- 'introduced=9000',
- 'introduced=9001',
+ Tag('introduced=9'),
+ Tag('introduced-arm=14'),
+ Tag('versioned=16'),
+ Tag('arm'),
+ Tag('introduced=9000'),
+ Tag('introduced=9001'),
]
self.assertListEqual(
expected_tags, symbolfile.decode_api_level_tags(tags, api_map))
with self.assertRaises(symbolfile.ParseError):
- symbolfile.decode_api_level_tags(['introduced=O'], {})
+ symbolfile.decode_api_level_tags([Tag('introduced=O')], {})
class PrivateVersionTest(unittest.TestCase):
- def test_version_is_private(self):
+ def test_version_is_private(self) -> None:
self.assertFalse(symbolfile.version_is_private('foo'))
self.assertFalse(symbolfile.version_is_private('PRIVATE'))
self.assertFalse(symbolfile.version_is_private('PLATFORM'))
@@ -110,191 +114,227 @@
class SymbolPresenceTest(unittest.TestCase):
- def test_symbol_in_arch(self):
- self.assertTrue(symbolfile.symbol_in_arch([], 'arm'))
- self.assertTrue(symbolfile.symbol_in_arch(['arm'], 'arm'))
+ def test_symbol_in_arch(self) -> None:
+ self.assertTrue(symbolfile.symbol_in_arch([], Arch('arm')))
+ self.assertTrue(symbolfile.symbol_in_arch([Tag('arm')], Arch('arm')))
- self.assertFalse(symbolfile.symbol_in_arch(['x86'], 'arm'))
+ self.assertFalse(symbolfile.symbol_in_arch([Tag('x86')], Arch('arm')))
- def test_symbol_in_api(self):
- self.assertTrue(symbolfile.symbol_in_api([], 'arm', 9))
- self.assertTrue(symbolfile.symbol_in_api(['introduced=9'], 'arm', 9))
- self.assertTrue(symbolfile.symbol_in_api(['introduced=9'], 'arm', 14))
- self.assertTrue(symbolfile.symbol_in_api(['introduced-arm=9'], 'arm', 14))
- self.assertTrue(symbolfile.symbol_in_api(['introduced-arm=9'], 'arm', 14))
- self.assertTrue(symbolfile.symbol_in_api(['introduced-x86=14'], 'arm', 9))
- self.assertTrue(symbolfile.symbol_in_api(
- ['introduced-arm=9', 'introduced-x86=21'], 'arm', 14))
- self.assertTrue(symbolfile.symbol_in_api(
- ['introduced=9', 'introduced-x86=21'], 'arm', 14))
- self.assertTrue(symbolfile.symbol_in_api(
- ['introduced=21', 'introduced-arm=9'], 'arm', 14))
- self.assertTrue(symbolfile.symbol_in_api(
- ['future'], 'arm', symbolfile.FUTURE_API_LEVEL))
+ def test_symbol_in_api(self) -> None:
+ self.assertTrue(symbolfile.symbol_in_api([], Arch('arm'), 9))
+ self.assertTrue(
+ symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 9))
+ self.assertTrue(
+ symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 14))
+ self.assertTrue(
+ symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'),
+ 14))
+ self.assertTrue(
+ symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'),
+ 14))
+ self.assertTrue(
+ symbolfile.symbol_in_api([Tag('introduced-x86=14')], Arch('arm'),
+ 9))
+ self.assertTrue(
+ symbolfile.symbol_in_api(
+ [Tag('introduced-arm=9'),
+ Tag('introduced-x86=21')], Arch('arm'), 14))
+ self.assertTrue(
+ symbolfile.symbol_in_api(
+ [Tag('introduced=9'),
+ Tag('introduced-x86=21')], Arch('arm'), 14))
+ self.assertTrue(
+ symbolfile.symbol_in_api(
+ [Tag('introduced=21'),
+ Tag('introduced-arm=9')], Arch('arm'), 14))
+ self.assertTrue(
+ symbolfile.symbol_in_api([Tag('future')], Arch('arm'),
+ symbolfile.FUTURE_API_LEVEL))
- self.assertFalse(symbolfile.symbol_in_api(['introduced=14'], 'arm', 9))
- self.assertFalse(symbolfile.symbol_in_api(['introduced-arm=14'], 'arm', 9))
- self.assertFalse(symbolfile.symbol_in_api(['future'], 'arm', 9))
- self.assertFalse(symbolfile.symbol_in_api(
- ['introduced=9', 'future'], 'arm', 14))
- self.assertFalse(symbolfile.symbol_in_api(
- ['introduced-arm=9', 'future'], 'arm', 14))
- self.assertFalse(symbolfile.symbol_in_api(
- ['introduced-arm=21', 'introduced-x86=9'], 'arm', 14))
- self.assertFalse(symbolfile.symbol_in_api(
- ['introduced=9', 'introduced-arm=21'], 'arm', 14))
- self.assertFalse(symbolfile.symbol_in_api(
- ['introduced=21', 'introduced-x86=9'], 'arm', 14))
+ self.assertFalse(
+ symbolfile.symbol_in_api([Tag('introduced=14')], Arch('arm'), 9))
+ self.assertFalse(
+ symbolfile.symbol_in_api([Tag('introduced-arm=14')], Arch('arm'),
+ 9))
+ self.assertFalse(
+ symbolfile.symbol_in_api([Tag('future')], Arch('arm'), 9))
+ self.assertFalse(
+ symbolfile.symbol_in_api(
+ [Tag('introduced=9'), Tag('future')], Arch('arm'), 14))
+ self.assertFalse(
+ symbolfile.symbol_in_api([Tag('introduced-arm=9'),
+ Tag('future')], Arch('arm'), 14))
+ self.assertFalse(
+ symbolfile.symbol_in_api(
+ [Tag('introduced-arm=21'),
+ Tag('introduced-x86=9')], Arch('arm'), 14))
+ self.assertFalse(
+ symbolfile.symbol_in_api(
+ [Tag('introduced=9'),
+ Tag('introduced-arm=21')], Arch('arm'), 14))
+ self.assertFalse(
+ symbolfile.symbol_in_api(
+ [Tag('introduced=21'),
+ Tag('introduced-x86=9')], Arch('arm'), 14))
# Interesting edge case: this symbol should be omitted from the
# library, but this call should still return true because none of the
# tags indiciate that it's not present in this API level.
- self.assertTrue(symbolfile.symbol_in_api(['x86'], 'arm', 9))
+ self.assertTrue(symbolfile.symbol_in_api([Tag('x86')], Arch('arm'), 9))
- def test_verioned_in_api(self):
+ def test_verioned_in_api(self) -> None:
self.assertTrue(symbolfile.symbol_versioned_in_api([], 9))
- self.assertTrue(symbolfile.symbol_versioned_in_api(['versioned=9'], 9))
- self.assertTrue(symbolfile.symbol_versioned_in_api(['versioned=9'], 14))
+ self.assertTrue(
+ symbolfile.symbol_versioned_in_api([Tag('versioned=9')], 9))
+ self.assertTrue(
+ symbolfile.symbol_versioned_in_api([Tag('versioned=9')], 14))
- self.assertFalse(symbolfile.symbol_versioned_in_api(['versioned=14'], 9))
+ self.assertFalse(
+ symbolfile.symbol_versioned_in_api([Tag('versioned=14')], 9))
class OmitVersionTest(unittest.TestCase):
- def test_omit_private(self):
+ def test_omit_private(self) -> None:
self.assertFalse(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, [], []), 'arm', 9, False,
+ symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False,
False))
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo_PRIVATE', None, [], []), 'arm', 9,
- False, False))
+ symbolfile.Version('foo_PRIVATE', None, [], []), Arch('arm'),
+ 9, False, False))
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo_PLATFORM', None, [], []), 'arm', 9,
- False, False))
-
- self.assertTrue(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['platform-only'], []), 'arm',
+ symbolfile.Version('foo_PLATFORM', None, [], []), Arch('arm'),
9, False, False))
- def test_omit_llndk(self):
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['llndk'], []), 'arm', 9,
- False, False))
+ symbolfile.Version('foo', None, [Tag('platform-only')], []),
+ Arch('arm'), 9, False, False))
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, [], []), 'arm', 9, True,
- False))
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['llndk'], []), 'arm', 9, True,
- False))
-
- def test_omit_apex(self):
+ def test_omit_llndk(self) -> None:
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['apex'], []), 'arm', 9, False,
- False))
+ symbolfile.Version('foo', None, [Tag('llndk')], []),
+ Arch('arm'), 9, False, False))
self.assertFalse(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, [], []), 'arm', 9, False,
+ symbolfile.Version('foo', None, [], []), Arch('arm'), 9, True,
+ False))
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [Tag('llndk')], []),
+ Arch('arm'), 9, True, False))
+
+ def test_omit_apex(self) -> None:
+ self.assertTrue(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [Tag('apex')], []),
+ Arch('arm'), 9, False, False))
+
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False,
True))
self.assertFalse(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['apex'], []), 'arm', 9, False,
- True))
+ symbolfile.Version('foo', None, [Tag('apex')], []),
+ Arch('arm'), 9, False, True))
- def test_omit_arch(self):
+ def test_omit_arch(self) -> None:
self.assertFalse(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, [], []), 'arm', 9, False,
+ symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False,
False))
self.assertFalse(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['arm'], []), 'arm', 9, False,
- False))
-
- self.assertTrue(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['x86'], []), 'arm', 9, False,
- False))
-
- def test_omit_api(self):
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, [], []), 'arm', 9, False,
- False))
- self.assertFalse(
- symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['introduced=9'], []), 'arm',
+ symbolfile.Version('foo', None, [Tag('arm')], []), Arch('arm'),
9, False, False))
self.assertTrue(
symbolfile.should_omit_version(
- symbolfile.Version('foo', None, ['introduced=14'], []), 'arm',
+ symbolfile.Version('foo', None, [Tag('x86')], []), Arch('arm'),
9, False, False))
+ def test_omit_api(self) -> None:
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False,
+ False))
+ self.assertFalse(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [Tag('introduced=9')], []),
+ Arch('arm'), 9, False, False))
+
+ self.assertTrue(
+ symbolfile.should_omit_version(
+ symbolfile.Version('foo', None, [Tag('introduced=14')], []),
+ Arch('arm'), 9, False, False))
+
class OmitSymbolTest(unittest.TestCase):
- def test_omit_llndk(self):
+ def test_omit_llndk(self) -> None:
self.assertTrue(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['llndk']),
- 'arm', 9, False, False))
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('llndk')]), Arch('arm'), 9,
+ False, False))
self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm',
- 9, True, False))
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['llndk']),
- 'arm', 9, True, False))
-
- def test_omit_apex(self):
- self.assertTrue(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['apex']),
- 'arm', 9, False, False))
-
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm',
- 9, False, True))
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['apex']),
- 'arm', 9, False, True))
-
- def test_omit_arch(self):
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm',
- 9, False, False))
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['arm']),
- 'arm', 9, False, False))
-
- self.assertTrue(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', ['x86']),
- 'arm', 9, False, False))
-
- def test_omit_api(self):
- self.assertFalse(
- symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []), 'arm',
- 9, False, False))
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, True, False))
self.assertFalse(
symbolfile.should_omit_symbol(
- symbolfile.Symbol('foo', ['introduced=9']), 'arm', 9, False,
+ symbolfile.Symbol('foo', [Tag('llndk')]), Arch('arm'), 9, True,
+ False))
+
+ def test_omit_apex(self) -> None:
+ self.assertTrue(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('apex')]), Arch('arm'), 9, False,
+ False))
+
+ self.assertFalse(
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, False, True))
+ self.assertFalse(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('apex')]), Arch('arm'), 9, False,
+ True))
+
+ def test_omit_arch(self) -> None:
+ self.assertFalse(
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, False, False))
+ self.assertFalse(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('arm')]), Arch('arm'), 9, False,
False))
self.assertTrue(
symbolfile.should_omit_symbol(
- symbolfile.Symbol('foo', ['introduced=14']), 'arm', 9, False,
+ symbolfile.Symbol('foo', [Tag('x86')]), Arch('arm'), 9, False,
False))
+ def test_omit_api(self) -> None:
+ self.assertFalse(
+ symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
+ Arch('arm'), 9, False, False))
+ self.assertFalse(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('introduced=9')]), Arch('arm'),
+ 9, False, False))
+
+ self.assertTrue(
+ symbolfile.should_omit_symbol(
+ symbolfile.Symbol('foo', [Tag('introduced=14')]), Arch('arm'),
+ 9, False, False))
+
class SymbolFileParseTest(unittest.TestCase):
- def test_next_line(self):
+ def test_next_line(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
foo
@@ -302,10 +342,12 @@
# baz
qux
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
self.assertIsNone(parser.current_line)
self.assertEqual('foo', parser.next_line().strip())
+ assert parser.current_line is not None
self.assertEqual('foo', parser.current_line.strip())
self.assertEqual('bar', parser.next_line().strip())
@@ -317,7 +359,7 @@
self.assertEqual('', parser.next_line())
self.assertEqual('', parser.current_line)
- def test_parse_version(self):
+ def test_parse_version(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 { # foo bar
baz;
@@ -327,7 +369,8 @@
VERSION_2 {
} VERSION_1; # asdf
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
parser.next_line()
version = parser.parse_version()
@@ -337,7 +380,7 @@
expected_symbols = [
symbolfile.Symbol('baz', []),
- symbolfile.Symbol('qux', ['woodly', 'doodly']),
+ symbolfile.Symbol('qux', [Tag('woodly'), Tag('doodly')]),
]
self.assertEqual(expected_symbols, version.symbols)
@@ -347,32 +390,35 @@
self.assertEqual('VERSION_1', version.base)
self.assertEqual([], version.tags)
- def test_parse_version_eof(self):
+ def test_parse_version_eof(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
parser.next_line()
with self.assertRaises(symbolfile.ParseError):
parser.parse_version()
- def test_unknown_scope_label(self):
+ def test_unknown_scope_label(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
foo:
}
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
parser.next_line()
with self.assertRaises(symbolfile.ParseError):
parser.parse_version()
- def test_parse_symbol(self):
+ def test_parse_symbol(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
foo;
bar; # baz qux
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
parser.next_line()
symbol = parser.parse_symbol()
@@ -384,48 +430,51 @@
self.assertEqual('bar', symbol.name)
self.assertEqual(['baz', 'qux'], symbol.tags)
- def test_wildcard_symbol_global(self):
+ def test_wildcard_symbol_global(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
*;
};
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
parser.next_line()
with self.assertRaises(symbolfile.ParseError):
parser.parse_version()
- def test_wildcard_symbol_local(self):
+ def test_wildcard_symbol_local(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
local:
*;
};
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
parser.next_line()
version = parser.parse_version()
self.assertEqual([], version.symbols)
- def test_missing_semicolon(self):
+ def test_missing_semicolon(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
foo
};
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
parser.next_line()
with self.assertRaises(symbolfile.ParseError):
parser.parse_version()
- def test_parse_fails_invalid_input(self):
+ def test_parse_fails_invalid_input(self) -> None:
with self.assertRaises(symbolfile.ParseError):
input_file = io.StringIO('foo')
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16,
- False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'),
+ 16, False, False)
parser.parse()
- def test_parse(self):
+ def test_parse(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
local:
@@ -443,23 +492,24 @@
qwerty;
} VERSION_1;
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, False)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, False)
versions = parser.parse()
expected = [
symbolfile.Version('VERSION_1', None, [], [
symbolfile.Symbol('foo', []),
- symbolfile.Symbol('bar', ['baz']),
+ symbolfile.Symbol('bar', [Tag('baz')]),
]),
- symbolfile.Version('VERSION_2', 'VERSION_1', ['wasd'], [
+ symbolfile.Version('VERSION_2', 'VERSION_1', [Tag('wasd')], [
symbolfile.Symbol('woodly', []),
- symbolfile.Symbol('doodly', ['asdf']),
+ symbolfile.Symbol('doodly', [Tag('asdf')]),
]),
]
self.assertEqual(expected, versions)
- def test_parse_llndk_apex_symbol(self):
+ def test_parse_llndk_apex_symbol(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
foo;
@@ -468,7 +518,8 @@
qux; # apex
};
"""))
- parser = symbolfile.SymbolFileParser(input_file, {}, 'arm', 16, False, True)
+ parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
+ False, True)
parser.next_line()
version = parser.parse_version()
@@ -477,14 +528,14 @@
expected_symbols = [
symbolfile.Symbol('foo', []),
- symbolfile.Symbol('bar', ['llndk']),
- symbolfile.Symbol('baz', ['llndk', 'apex']),
- symbolfile.Symbol('qux', ['apex']),
+ symbolfile.Symbol('bar', [Tag('llndk')]),
+ symbolfile.Symbol('baz', [Tag('llndk'), Tag('apex')]),
+ symbolfile.Symbol('qux', [Tag('apex')]),
]
self.assertEqual(expected_symbols, version.symbols)
-def main():
+def main() -> None:
suite = unittest.TestLoader().loadTestsFromName(__name__)
unittest.TextTestRunner(verbosity=3).run(suite)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 8b66dbf..33f422d 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -253,6 +253,10 @@
// if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
Create_doc_stubs *bool
+ // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
+ // Has no effect if create_doc_stubs: true.
+ Output_javadoc_comments *bool
+
// if set to false then do not write out stubs. Defaults to true.
//
// TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
@@ -1150,7 +1154,9 @@
cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
} else {
cmd.FlagWithArg("--stubs ", stubsDir.String())
- cmd.Flag("--exclude-documentation-from-stubs")
+ if !Bool(d.properties.Output_javadoc_comments) {
+ cmd.Flag("--exclude-documentation-from-stubs")
+ }
}
}
}
diff --git a/java/java_test.go b/java/java_test.go
index 9e63577..f16639a 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1487,6 +1487,12 @@
libs: ["foo"],
sdk_version: "system_29",
}
+ java_library {
+ name: "baz-module-30",
+ srcs: ["c.java"],
+ libs: ["foo"],
+ sdk_version: "module_30",
+ }
`)
// check the existence of the internal modules
@@ -1533,6 +1539,13 @@
"prebuilts/sdk/29/system/foo.jar")
}
+ bazModule30Javac := ctx.ModuleForTests("baz-module-30", "android_common").Rule("javac")
+ // tests if "baz-module-30" is actually linked to the module 30 stubs lib
+ if !strings.Contains(bazModule30Javac.Args["classpath"], "prebuilts/sdk/30/module-lib/foo.jar") {
+ t.Errorf("baz-module-30 javac classpath %v does not contain %q", bazModule30Javac.Args["classpath"],
+ "prebuilts/sdk/30/module-lib/foo.jar")
+ }
+
// test if baz has exported SDK lib names foo and bar to qux
qux := ctx.ModuleForTests("qux", "android_common")
if quxLib, ok := qux.Module().(*Library); ok {
diff --git a/java/sdk.go b/java/sdk.go
index f599265..971791f 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -222,7 +222,7 @@
return ctx.Config().AlwaysUsePrebuiltSdks()
} else if s.version.isNumbered() {
// validation check
- if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest {
+ if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest && s.kind != sdkModule {
panic(fmt.Errorf("prebuilt SDK is not not available for sdkKind=%q", s.kind))
return false
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index a7b92b3..60924a6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -589,6 +589,9 @@
// An Android shared library is one that can be referenced in a <uses-library> element
// in an AndroidManifest.xml.
Shared_library *bool
+
+ // Files containing information about supported java doc tags.
+ Doctag_files []string `android:"path"`
}
// Common code between sdk library and sdk library import
@@ -601,6 +604,9 @@
commonSdkLibraryProperties commonToSdkLibraryAndImportProperties
+ // Paths to commonSdkLibraryProperties.Doctag_files
+ doctagPaths android.Paths
+
// Functionality related to this being used as a component of a java_sdk_library.
EmbeddableSdkLibraryComponent
}
@@ -633,6 +639,10 @@
return true
}
+func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) {
+ c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
+}
+
// Module name of the runtime implementation library
func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
return c.moduleBase.BaseModuleName() + ".impl"
@@ -732,6 +742,14 @@
}
} else {
+ switch tag {
+ case ".doctags":
+ if c.doctagPaths != nil {
+ return c.doctagPaths, nil
+ } else {
+ return nil, fmt.Errorf("no doctag_files specified on %s", c.moduleBase.BaseModuleName())
+ }
+ }
return nil, nil
}
}
@@ -1014,6 +1032,8 @@
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ module.generateCommonBuildActions(ctx)
+
// Only build an implementation library if required.
if module.requiresRuntimeImplementationLibrary() {
module.Library.GenerateAndroidBuildActions(ctx)
@@ -1203,6 +1223,7 @@
Sdk_version *string
System_modules *string
Libs []string
+ Output_javadoc_comments *bool
Arg_files []string
Args *string
Java_version *string
@@ -1278,6 +1299,11 @@
}
droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
+ // Output Javadoc comments for public scope.
+ if apiScope == apiScopePublic {
+ props.Output_javadoc_comments = proptools.BoolPtr(true)
+ }
+
// Add in scope specific arguments.
droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
@@ -1889,6 +1915,8 @@
}
func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ module.generateCommonBuildActions(ctx)
+
// Record the paths to the prebuilt stubs library and stubs source.
ctx.VisitDirectDeps(func(to android.Module) {
tag := ctx.OtherModuleDependencyTag(to)
@@ -2181,6 +2209,9 @@
// True if the java_sdk_library_import is for a shared library, false
// otherwise.
Shared_library *bool
+
+ // The paths to the doctag files to add to the prebuilt.
+ Doctag_paths android.Paths
}
type scopeProperties struct {
@@ -2220,6 +2251,7 @@
s.Libs = sdk.properties.Libs
s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
+ s.Doctag_paths = sdk.doctagPaths
}
func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -2268,6 +2300,16 @@
}
}
+ if len(s.Doctag_paths) > 0 {
+ dests := []string{}
+ for _, p := range s.Doctag_paths {
+ dest := filepath.Join("doctags", p.Rel())
+ ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
+ dests = append(dests, dest)
+ }
+ propertySet.AddProperty("doctag_files", dests)
+ }
+
if len(s.Libs) > 0 {
propertySet.AddPropertyWithTag("libs", s.Libs, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(false))
}
diff --git a/java/testing.go b/java/testing.go
index a472413..461fd3f 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -55,6 +55,8 @@
"prebuilts/sdk/30/public/framework.aidl": nil,
"prebuilts/sdk/30/system/android.jar": nil,
"prebuilts/sdk/30/system/foo.jar": nil,
+ "prebuilts/sdk/30/module-lib/android.jar": nil,
+ "prebuilts/sdk/30/module-lib/foo.jar": nil,
"prebuilts/sdk/30/public/core-for-system-modules.jar": nil,
"prebuilts/sdk/current/core/android.jar": nil,
"prebuilts/sdk/current/public/android.jar": nil,
diff --git a/python/androidmk.go b/python/androidmk.go
index 247b80d..8ad5889 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -15,11 +15,12 @@
package python
import (
- "android/soong/android"
"fmt"
"io"
"path/filepath"
"strings"
+
+ "android/soong/android"
)
type subAndroidMkProvider interface {
@@ -74,6 +75,11 @@
if !BoolDefault(p.binaryProperties.Auto_gen_config, true) {
fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true")
}
+
+ if len(p.data) > 0 {
+ fmt.Fprintln(w, "LOCAL_TEST_DATA :=",
+ strings.Join(android.AndroidMkDataPaths(p.data), " "))
+ }
})
base.subAndroidMk(ret, p.binaryDecorator.pythonInstaller)
}
diff --git a/python/test.go b/python/test.go
index a669c73..434e71a 100644
--- a/python/test.go
+++ b/python/test.go
@@ -34,6 +34,10 @@
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
Test_config_template *string `android:"path,arch_variant"`
+
+ // list of files or filegroup modules that provide data that should be installed alongside
+ // the test
+ Data []string `android:"path,arch_variant"`
}
type testDecorator struct {
@@ -42,6 +46,8 @@
testProperties TestProperties
testConfig android.Path
+
+ data []android.DataPath
}
func (test *testDecorator) bootstrapperProps() []interface{} {
@@ -59,6 +65,12 @@
test.binaryDecorator.pythonInstaller.relative = ctx.ModuleName()
test.binaryDecorator.pythonInstaller.install(ctx, file)
+
+ dataSrcPaths := android.PathsForModuleSrc(ctx, test.testProperties.Data)
+
+ for _, dataSrcPath := range dataSrcPaths {
+ test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
+ }
}
func NewTest(hod android.HostOrDeviceSupported) *Module {
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 62d469e..483dddb 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -1,6 +1,10 @@
package config
var (
+ // When adding a new path below, add a rustfmt.toml file at the root of
+ // the repository and enable the rustfmt repo hook. See aosp/1347562
+ // for an example.
+ // TODO(b/160223496): enable rustfmt globally.
RustAllowedPaths = []string{
"external/minijail",
"external/rust",
diff --git a/rust/project_json.go b/rust/project_json.go
index 8310479..8d161b2 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -30,16 +30,6 @@
//
// $ SOONG_GEN_RUST_PROJECT=1 m nothing
-func init() {
- android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
-}
-
-func rustProjectGeneratorSingleton() android.Singleton {
- return &projectGeneratorSingleton{}
-}
-
-type projectGeneratorSingleton struct{}
-
const (
// Environment variables used to control the behavior of this singleton.
envVariableCollectRustDeps = "SOONG_GEN_RUST_PROJECT"
@@ -49,6 +39,7 @@
// The format of rust-project.json is not yet finalized. A current description is available at:
// https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc#non-cargo-based-projects
type rustProjectDep struct {
+ // The Crate attribute is the index of the dependency in the Crates array in rustProjectJson.
Crate int `json:"crate"`
Name string `json:"name"`
}
@@ -71,12 +62,50 @@
Deps map[string]int
}
-func mergeDependencies(ctx android.SingletonContext, project *rustProjectJson,
- knownCrates map[string]crateInfo, module android.Module,
- crate *rustProjectCrate, deps map[string]int) {
+type projectGeneratorSingleton struct {
+ project rustProjectJson
+ knownCrates map[string]crateInfo
+}
+
+func rustProjectGeneratorSingleton() android.Singleton {
+ return &projectGeneratorSingleton{}
+}
+
+func init() {
+ android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
+}
+
+// librarySource finds the main source file (.rs) for a crate.
+func librarySource(ctx android.SingletonContext, rModule *Module, rustLib *libraryDecorator) (string, bool) {
+ srcs := rustLib.baseCompiler.Properties.Srcs
+ if len(srcs) != 0 {
+ return path.Join(ctx.ModuleDir(rModule), srcs[0]), true
+ }
+ if !rustLib.source() {
+ return "", false
+ }
+ // It is a SourceProvider module. If this module is host only, uses the variation for the host.
+ // Otherwise, use the variation for the primary target.
+ switch rModule.hod {
+ case android.HostSupported:
+ case android.HostSupportedNoCross:
+ if rModule.Target().String() != ctx.Config().BuildOSTarget.String() {
+ return "", false
+ }
+ default:
+ if rModule.Target().String() != ctx.Config().Targets[android.Android][0].String() {
+ return "", false
+ }
+ }
+ src := rustLib.sourceProvider.Srcs()[0]
+ return src.String(), true
+}
+
+func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext,
+ module android.Module, crate *rustProjectCrate, deps map[string]int) {
ctx.VisitDirectDeps(module, func(child android.Module) {
- childId, childCrateName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
+ childId, childCrateName, ok := singleton.appendLibraryAndDeps(ctx, child)
if !ok {
return
}
@@ -88,12 +117,10 @@
})
}
-// appendLibraryAndDeps creates a rustProjectCrate for the module argument and
-// appends it to the rustProjectJson struct. It visits the dependencies of the
-// module depth-first. If the current module is already in knownCrates, its
-// dependencies are merged. Returns a tuple (id, crate_name, ok).
-func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson,
- knownCrates map[string]crateInfo, module android.Module) (int, string, bool) {
+// appendLibraryAndDeps creates a rustProjectCrate for the module argument and appends it to singleton.project.
+// It visits the dependencies of the module depth-first so the dependency ID can be added to the current module. If the
+// current module is already in singleton.knownCrates, its dependencies are merged. Returns a tuple (id, crate_name, ok).
+func (singleton *projectGeneratorSingleton) appendLibraryAndDeps(ctx android.SingletonContext, module android.Module) (int, string, bool) {
rModule, ok := module.(*Module)
if !ok {
return 0, "", false
@@ -107,46 +134,45 @@
}
moduleName := ctx.ModuleName(module)
crateName := rModule.CrateName()
- if cInfo, ok := knownCrates[moduleName]; ok {
+ if cInfo, ok := singleton.knownCrates[moduleName]; ok {
// We have seen this crate already; merge any new dependencies.
- crate := project.Crates[cInfo.ID]
- mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps)
- project.Crates[cInfo.ID] = crate
+ crate := singleton.project.Crates[cInfo.ID]
+ singleton.mergeDependencies(ctx, module, &crate, cInfo.Deps)
+ singleton.project.Crates[cInfo.ID] = crate
return cInfo.ID, crateName, true
}
crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
- srcs := rustLib.baseCompiler.Properties.Srcs
- if len(srcs) == 0 {
+ rootModule, ok := librarySource(ctx, rModule, rustLib)
+ if !ok {
return 0, "", false
}
- crate.RootModule = path.Join(ctx.ModuleDir(rModule), srcs[0])
+ crate.RootModule = rootModule
crate.Edition = rustLib.baseCompiler.edition()
deps := make(map[string]int)
- mergeDependencies(ctx, project, knownCrates, module, &crate, deps)
+ singleton.mergeDependencies(ctx, module, &crate, deps)
- id := len(project.Crates)
- knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
- project.Crates = append(project.Crates, crate)
+ id := len(singleton.project.Crates)
+ singleton.knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
+ singleton.project.Crates = append(singleton.project.Crates, crate)
// rust-analyzer requires that all crates belong to at least one root:
// https://github.com/rust-analyzer/rust-analyzer/issues/4735.
- project.Roots = append(project.Roots, path.Dir(crate.RootModule))
+ singleton.project.Roots = append(singleton.project.Roots, path.Dir(crate.RootModule))
return id, crateName, true
}
-func (r *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
if !ctx.Config().IsEnvTrue(envVariableCollectRustDeps) {
return
}
- project := rustProjectJson{}
- knownCrates := make(map[string]crateInfo)
+ singleton.knownCrates = make(map[string]crateInfo)
ctx.VisitAllModules(func(module android.Module) {
- appendLibraryAndDeps(ctx, &project, knownCrates, module)
+ singleton.appendLibraryAndDeps(ctx, module)
})
path := android.PathForOutput(ctx, rustProjectJsonFileName)
- err := createJsonFile(project, path)
+ err := createJsonFile(singleton.project, path)
if err != nil {
ctx.Errorf(err.Error())
}
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 8521940..11964f3 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -18,6 +18,7 @@
"encoding/json"
"io/ioutil"
"path/filepath"
+ "strings"
"testing"
"android/soong/android"
@@ -100,22 +101,51 @@
rust_library {
name: "liba",
srcs: ["src/lib.rs"],
- rlibs: ["libbindings"],
+ rlibs: ["libbindings1"],
crate_name: "a"
}
rust_bindgen {
- name: "libbindings",
- crate_name: "bindings",
- source_stem: "bindings",
+ name: "libbindings1",
+ crate_name: "bindings1",
+ source_stem: "bindings1",
host_supported: true,
wrapper_src: "src/any.h",
}
+ rust_library_host {
+ name: "libb",
+ srcs: ["src/lib.rs"],
+ rustlibs: ["libbindings2"],
+ crate_name: "b"
+ }
+ rust_bindgen_host {
+ name: "libbindings2",
+ crate_name: "bindings2",
+ source_stem: "bindings2",
+ wrapper_src: "src/any.h",
+ }
` + GatherRequiredDepsForTest()
fs := map[string][]byte{
"src/lib.rs": nil,
}
jsonContent := testProjectJson(t, bp, fs)
- validateJsonCrates(t, jsonContent)
+ crates := validateJsonCrates(t, jsonContent)
+ for _, c := range crates {
+ crate, ok := c.(map[string]interface{})
+ if !ok {
+ t.Fatalf("Unexpected type for crate: %v", c)
+ }
+ rootModule, ok := crate["root_module"].(string)
+ if !ok {
+ t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
+ }
+ if strings.Contains(rootModule, "libbindings1") && !strings.Contains(rootModule, "android_arm64") {
+ t.Errorf("The source path for libbindings1 does not contain android_arm64, got %v", rootModule)
+ }
+ if strings.Contains(rootModule, "libbindings2") && !strings.Contains(rootModule, android.BuildOs.String()) {
+ t.Errorf("The source path for libbindings2 does not contain the BuildOs, got %v; want %v",
+ rootModule, android.BuildOs.String())
+ }
+ }
}
func TestProjectJsonMultiVersion(t *testing.T) {
diff --git a/rust/rust.go b/rust/rust.go
index f88b310..68e5a5b 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -695,6 +695,11 @@
if mod.compiler.(libraryInterface).source() {
mod.sourceProvider.GenerateSource(ctx, deps)
mod.sourceProvider.setSubName(ctx.ModuleSubDir())
+ if lib, ok := mod.compiler.(*libraryDecorator); ok {
+ lib.flagExporter.linkDirs = nil
+ lib.flagExporter.linkObjects = nil
+ lib.flagExporter.depFlags = nil
+ }
} else {
sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag)
sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
diff --git a/rust/testing.go b/rust/testing.go
index ee303ed..42b0da1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -117,6 +117,7 @@
ctx.RegisterModuleType("rust_binary", RustBinaryFactory)
ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory)
ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory)
+ ctx.RegisterModuleType("rust_bindgen_host", RustBindgenHostFactory)
ctx.RegisterModuleType("rust_test", RustTestFactory)
ctx.RegisterModuleType("rust_test_host", RustTestHostFactory)
ctx.RegisterModuleType("rust_library", RustLibraryFactory)
diff --git a/sdk/bp.go b/sdk/bp.go
index 68fe7ab..11ec8c6 100644
--- a/sdk/bp.go
+++ b/sdk/bp.go
@@ -16,6 +16,8 @@
import (
"fmt"
+ "reflect"
+ "strings"
"android/soong/android"
)
@@ -33,7 +35,82 @@
s.tags = make(map[string]android.BpPropertyTag)
}
+// Converts the given value, which is assumed to be a struct, to a
+// bpPropertySet.
+func convertToPropertySet(value reflect.Value) *bpPropertySet {
+ res := newPropertySet()
+ structType := value.Type()
+
+ for i := 0; i < structType.NumField(); i++ {
+ field := structType.Field(i)
+ fieldVal := value.Field(i)
+
+ switch fieldVal.Type().Kind() {
+ case reflect.Ptr:
+ if fieldVal.IsNil() {
+ continue // nil pointer means the property isn't set.
+ }
+ fieldVal = fieldVal.Elem()
+ case reflect.Slice:
+ if fieldVal.IsNil() {
+ continue // Ignore a nil slice (but not one with length zero).
+ }
+ }
+
+ if fieldVal.Type().Kind() == reflect.Struct {
+ fieldVal = fieldVal.Addr() // Avoid struct copy below.
+ }
+ res.AddProperty(strings.ToLower(field.Name), fieldVal.Interface())
+ }
+
+ return res
+}
+
+// Converts the given value to something that can be set in a property.
+func coercePropertyValue(value interface{}) interface{} {
+ val := reflect.ValueOf(value)
+ switch val.Kind() {
+ case reflect.Struct:
+ // convertToPropertySet requires an addressable struct, and this is probably
+ // a mistake.
+ panic(fmt.Sprintf("Value is a struct, not a pointer to one: %v", value))
+ case reflect.Ptr:
+ if _, ok := value.(*bpPropertySet); !ok {
+ derefValue := reflect.Indirect(val)
+ if derefValue.Kind() != reflect.Struct {
+ panic(fmt.Sprintf("A pointer must be to a struct, got: %v", value))
+ }
+ return convertToPropertySet(derefValue)
+ }
+ }
+ return value
+}
+
+// Merges the fields of the given property set into s.
+func (s *bpPropertySet) mergePropertySet(propSet *bpPropertySet) {
+ for _, name := range propSet.order {
+ if tag, ok := propSet.tags[name]; ok {
+ s.AddPropertyWithTag(name, propSet.properties[name], tag)
+ } else {
+ s.AddProperty(name, propSet.properties[name])
+ }
+ }
+}
+
func (s *bpPropertySet) AddProperty(name string, value interface{}) {
+ value = coercePropertyValue(value)
+
+ if propSetValue, ok := value.(*bpPropertySet); ok {
+ if curValue, ok := s.properties[name]; ok {
+ if curSet, ok := curValue.(*bpPropertySet); ok {
+ curSet.mergePropertySet(propSetValue)
+ return
+ }
+ // If the current value isn't a property set we got conflicting types.
+ // Continue down to the check below to complain about it.
+ }
+ }
+
if s.properties[name] != nil {
panic(fmt.Sprintf("Property %q already exists in property set", name))
}
@@ -48,9 +125,8 @@
}
func (s *bpPropertySet) AddPropertySet(name string) android.BpPropertySet {
- set := newPropertySet()
- s.AddProperty(name, set)
- return set
+ s.AddProperty(name, newPropertySet())
+ return s.properties[name].(android.BpPropertySet)
}
func (s *bpPropertySet) getValue(name string) interface{} {
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index c630c25..e1edc51 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -18,8 +18,142 @@
"testing"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
+func propertySetFixture() interface{} {
+ set := newPropertySet()
+ set.AddProperty("x", "taxi")
+ set.AddPropertyWithTag("y", 1729, "tag_y")
+ subset := set.AddPropertySet("sub")
+ subset.AddPropertyWithTag("x", "taxi", "tag_x")
+ subset.AddProperty("y", 1729)
+ return set
+}
+
+func intPtr(i int) *int { return &i }
+
+type propertyStruct struct {
+ X *string
+ Y *int
+ Unset *bool
+ Sub struct {
+ X *string
+ Y *int
+ Unset *bool
+ }
+}
+
+func propertyStructFixture() interface{} {
+ str := &propertyStruct{}
+ str.X = proptools.StringPtr("taxi")
+ str.Y = intPtr(1729)
+ str.Sub.X = proptools.StringPtr("taxi")
+ str.Sub.Y = intPtr(1729)
+ return str
+}
+
+func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) {
+ set := val.(*bpPropertySet)
+ h.AssertDeepEquals("wrong x value", "taxi", set.getValue("x"))
+ h.AssertDeepEquals("wrong y value", 1729, set.getValue("y"))
+
+ subset := set.getValue("sub").(*bpPropertySet)
+ h.AssertDeepEquals("wrong sub.x value", "taxi", subset.getValue("x"))
+ h.AssertDeepEquals("wrong sub.y value", 1729, subset.getValue("y"))
+
+ if hasTags {
+ h.AssertDeepEquals("wrong y tag", "tag_y", set.getTag("y"))
+ h.AssertDeepEquals("wrong sub.x tag", "tag_x", subset.getTag("x"))
+ } else {
+ h.AssertDeepEquals("wrong y tag", nil, set.getTag("y"))
+ h.AssertDeepEquals("wrong sub.x tag", nil, subset.getTag("x"))
+ }
+}
+
+func TestAddPropertySimple(t *testing.T) {
+ h := &TestHelper{t}
+ set := newPropertySet()
+ for name, val := range map[string]interface{}{
+ "x": "taxi",
+ "y": 1729,
+ "t": true,
+ "f": false,
+ "arr": []string{"a", "b", "c"},
+ } {
+ set.AddProperty(name, val)
+ h.AssertDeepEquals("wrong value", val, set.getValue(name))
+ }
+ h.AssertPanic("adding x again should panic",
+ func() { set.AddProperty("x", "taxi") })
+ h.AssertPanic("adding arr again should panic",
+ func() { set.AddProperty("arr", []string{"d"}) })
+}
+
+func TestAddPropertySubset(t *testing.T) {
+ h := &TestHelper{t}
+ getFixtureMap := map[string]func() interface{}{
+ "property set": propertySetFixture,
+ "property struct": propertyStructFixture,
+ }
+
+ t.Run("add new subset", func(t *testing.T) {
+ for name, getFixture := range getFixtureMap {
+ t.Run(name, func(t *testing.T) {
+ set := propertySetFixture().(*bpPropertySet)
+ set.AddProperty("new", getFixture())
+ checkPropertySetFixture(h, set, true)
+ checkPropertySetFixture(h, set.getValue("new"), name == "property set")
+ })
+ }
+ })
+
+ t.Run("merge existing subset", func(t *testing.T) {
+ for name, getFixture := range getFixtureMap {
+ t.Run(name, func(t *testing.T) {
+ set := newPropertySet()
+ subset := set.AddPropertySet("sub")
+ subset.AddProperty("flag", false)
+ subset.AddPropertySet("sub")
+ set.AddProperty("sub", getFixture())
+ merged := set.getValue("sub").(*bpPropertySet)
+ h.AssertDeepEquals("wrong flag value", false, merged.getValue("flag"))
+ checkPropertySetFixture(h, merged, name == "property set")
+ })
+ }
+ })
+
+ t.Run("add conflicting subset", func(t *testing.T) {
+ set := propertySetFixture().(*bpPropertySet)
+ h.AssertPanic("adding x again should panic",
+ func() { set.AddProperty("x", propertySetFixture()) })
+ })
+
+ t.Run("add non-pointer struct", func(t *testing.T) {
+ set := propertySetFixture().(*bpPropertySet)
+ str := propertyStructFixture().(*propertyStruct)
+ h.AssertPanic("adding a non-pointer struct should panic",
+ func() { set.AddProperty("new", *str) })
+ })
+}
+
+func TestAddPropertySetNew(t *testing.T) {
+ h := &TestHelper{t}
+ set := newPropertySet()
+ subset := set.AddPropertySet("sub")
+ subset.AddProperty("new", "d^^b")
+ h.AssertDeepEquals("wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new"))
+}
+
+func TestAddPropertySetExisting(t *testing.T) {
+ h := &TestHelper{t}
+ set := propertySetFixture().(*bpPropertySet)
+ subset := set.AddPropertySet("sub")
+ subset.AddProperty("new", "d^^b")
+ h.AssertDeepEquals("wrong sub.new value", "d^^b", set.getValue("sub").(*bpPropertySet).getValue("new"))
+}
+
type removeFredTransformation struct {
identityTransformation
}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 8c9e228..17a6d86 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -435,8 +435,10 @@
)
}
-// Verify that when the shared library has some common and some arch specific properties that the generated
-// snapshot is optimized properly.
+// Verify that when the shared library has some common and some arch specific
+// properties that the generated snapshot is optimized properly. Substruct
+// handling is tested with the sanitize clauses (but note there's a lot of
+// built-in logic in sanitize.go that can affect those flags).
func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
@@ -451,9 +453,18 @@
"aidl/foo/bar/Test.aidl",
],
export_include_dirs: ["include"],
+ sanitize: {
+ fuzzer: false,
+ integer_overflow: true,
+ diag: { undefined: false },
+ },
arch: {
arm64: {
export_system_include_dirs: ["arm64/include"],
+ sanitize: {
+ hwaddress: true,
+ integer_overflow: false,
+ },
},
},
stl: "none",
@@ -471,13 +482,26 @@
stl: "none",
compile_multilib: "both",
export_include_dirs: ["include/include"],
+ sanitize: {
+ fuzzer: false,
+ diag: {
+ undefined: false,
+ },
+ },
arch: {
arm64: {
srcs: ["arm64/lib/mynativelib.so"],
export_system_include_dirs: ["arm64/include/arm64/include"],
+ sanitize: {
+ hwaddress: true,
+ integer_overflow: false,
+ },
},
arm: {
srcs: ["arm/lib/mynativelib.so"],
+ sanitize: {
+ integer_overflow: true,
+ },
},
},
}
@@ -488,13 +512,26 @@
stl: "none",
compile_multilib: "both",
export_include_dirs: ["include/include"],
+ sanitize: {
+ fuzzer: false,
+ diag: {
+ undefined: false,
+ },
+ },
arch: {
arm64: {
srcs: ["arm64/lib/mynativelib.so"],
export_system_include_dirs: ["arm64/include/arm64/include"],
+ sanitize: {
+ hwaddress: true,
+ integer_overflow: false,
+ },
},
arm: {
srcs: ["arm/lib/mynativelib.so"],
+ sanitize: {
+ integer_overflow: true,
+ },
},
},
}
@@ -506,7 +543,7 @@
`),
checkAllCopyRules(`
include/Test.h -> include/include/Test.h
-.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
+.intermediates/mynativelib/android_arm64_armv8-a_shared_hwasan/mynativelib.so -> arm64/lib/mynativelib.so
arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
)
@@ -2330,7 +2367,11 @@
installable: false,
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
arch: {
arm64: {
@@ -2347,7 +2388,11 @@
prefer: false,
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
arch: {
arm64: {
@@ -2401,7 +2446,11 @@
installable: false,
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
target: {
host: {
@@ -2431,7 +2480,11 @@
host_supported: true,
compile_multilib: "both",
stubs: {
- versions: ["3"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
},
target: {
host: {
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index a7ee8d1..23ecb6d 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -43,6 +43,7 @@
"api/system-server-current.txt": nil,
"api/system-server-removed.txt": nil,
"build/soong/scripts/gen-java-current-api-files.sh": nil,
+ "docs/known_doctags": nil,
}
// for java_sdk_library tests
@@ -1590,3 +1591,72 @@
),
)
}
+
+func TestSnapshotWithJavaSdkLibrary_DoctagFiles(t *testing.T) {
+ result := testSdkWithJava(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib",
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ doctag_files: ["docs/known_doctags"],
+ }
+
+ filegroup {
+ name: "mygroup",
+ srcs: [":myjavalib{.doctags}"],
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "mysdk_myjavalib@current",
+ sdk_member_name: "myjavalib",
+ shared_library: true,
+ doctag_files: ["doctags/docs/known_doctags"],
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+}
+
+java_sdk_library_import {
+ name: "myjavalib",
+ prefer: false,
+ shared_library: true,
+ doctag_files: ["doctags/docs/known_doctags"],
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ java_sdk_libs: ["mysdk_myjavalib@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+docs/known_doctags -> doctags/docs/known_doctags
+`),
+ )
+}
diff --git a/sdk/testing.go b/sdk/testing.go
index e57f1f7..0b280ef 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -94,6 +94,7 @@
// from android package
android.RegisterPackageBuildComponents(ctx)
+ ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(android.RegisterComponentsMutator)
@@ -217,6 +218,22 @@
}
}
+func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) {
+ h.t.Helper()
+ panicked := false
+ func() {
+ defer func() {
+ if x := recover(); x != nil {
+ panicked = true
+ }
+ }()
+ funcThatShouldPanic()
+ }()
+ if !panicked {
+ h.t.Error(message)
+ }
+}
+
// Encapsulates result of processing an SDK definition. Provides support for
// checking the state of the build structures.
type testSdkResult struct {
diff --git a/sdk/update.go b/sdk/update.go
index 3c4309c..a10e852 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -1346,7 +1346,8 @@
// A property that can be optimized by the commonValueExtractor.
type extractorProperty struct {
- // The name of the field for this property.
+ // The name of the field for this property. It is a "."-separated path for
+ // fields in non-anonymous substructs.
name string
// Filter that can use metadata associated with the properties being optimized
@@ -1383,18 +1384,18 @@
func newCommonValueExtractor(propertiesStruct interface{}) *commonValueExtractor {
structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type()
extractor := &commonValueExtractor{}
- extractor.gatherFields(structType, nil)
+ extractor.gatherFields(structType, nil, "")
return extractor
}
// Gather the fields from the supplied structure type from which common values will
// be extracted.
//
-// This is recursive function. If it encounters an embedded field (no field name)
-// that is a struct then it will recurse into that struct passing in the accessor
-// for the field. That will then be used in the accessors for the fields in the
-// embedded struct.
-func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc) {
+// This is recursive function. If it encounters a struct then it will recurse
+// into it, passing in the accessor for the field and the struct name as prefix
+// for the nested fields. That will then be used in the accessors for the fields
+// in the embedded struct.
+func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc, namePrefix string) {
for f := 0; f < structType.NumField(); f++ {
field := structType.Field(f)
if field.PkgPath != "" {
@@ -1424,7 +1425,7 @@
// Save a copy of the field index for use in the function.
fieldIndex := f
- name := field.Name
+ name := namePrefix + field.Name
fieldGetter := func(value reflect.Value) reflect.Value {
if containingStructAccessor != nil {
@@ -1446,9 +1447,15 @@
return value.Field(fieldIndex)
}
- if field.Type.Kind() == reflect.Struct && field.Anonymous {
- // Gather fields from the embedded structure.
- e.gatherFields(field.Type, fieldGetter)
+ if field.Type.Kind() == reflect.Struct {
+ // Gather fields from the nested or embedded structure.
+ var subNamePrefix string
+ if field.Anonymous {
+ subNamePrefix = namePrefix
+ } else {
+ subNamePrefix = name + "."
+ }
+ e.gatherFields(field.Type, fieldGetter, subNamePrefix)
} else {
property := extractorProperty{
name,
@@ -1512,7 +1519,8 @@
// Iterates over each exported field (capitalized name) and checks to see whether they
// have the same value (using DeepEquals) across all the input properties. If it does not then no
// change is made. Otherwise, the common value is stored in the field in the commonProperties
-// and the field in each of the input properties structure is set to its default value.
+// and the field in each of the input properties structure is set to its default value. Nested
+// structs are visited recursively and their non-struct fields are compared.
func (e *commonValueExtractor) extractCommonProperties(commonProperties interface{}, inputPropertiesSlice interface{}) error {
commonPropertiesValue := reflect.ValueOf(commonProperties)
commonStructValue := commonPropertiesValue.Elem()
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index f3f4a4a..7c3cdbd 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -313,6 +313,15 @@
options := []tradefed.Option{{Name: "force-root", Value: "false"}}
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
}
+ if len(s.testProperties.Data_device_bins) > 0 {
+ moduleName := s.Name()
+ remoteDir := "/data/local/tests/unrestricted/" + moduleName + "/"
+ options := []tradefed.Option{{Name: "cleanup", Value: "true"}}
+ for _, bin := range s.testProperties.Data_device_bins {
+ options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: remoteDir + bin})
+ }
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options})
+ }
s.testConfig = tradefed.AutoGenShellTestConfig(ctx, s.testProperties.Test_config,
s.testProperties.Test_config_template, s.testProperties.Test_suites, configs, s.testProperties.Auto_gen_config, s.outputFilePath.Base())
diff --git a/ui/build/config.go b/ui/build/config.go
index 27f3be3..fe74ace 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -298,8 +298,9 @@
}
b := &smpb.BuildConfig{
- UseGoma: proto.Bool(config.UseGoma()),
- UseRbe: proto.Bool(config.UseRBE()),
+ ForceUseGoma: proto.Bool(config.ForceUseGoma()),
+ UseGoma: proto.Bool(config.UseGoma()),
+ UseRbe: proto.Bool(config.UseRBE()),
}
ctx.Metrics.BuildConfig(b)
}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index d7c53ec..05efe13 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -399,6 +399,7 @@
type BuildConfig struct {
UseGoma *bool `protobuf:"varint,1,opt,name=use_goma,json=useGoma" json:"use_goma,omitempty"`
UseRbe *bool `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"`
+ ForceUseGoma *bool `protobuf:"varint,3,opt,name=force_use_goma,json=forceUseGoma" json:"force_use_goma,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -443,6 +444,13 @@
return false
}
+func (m *BuildConfig) GetForceUseGoma() bool {
+ if m != nil && m.ForceUseGoma != nil {
+ return *m.ForceUseGoma
+ }
+ return false
+}
+
type PerfInfo struct {
// The description for the phase/action/part while the tool running.
Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"`
@@ -764,69 +772,70 @@
}
var fileDescriptor_6039342a2ba47b72 = []byte{
- // 1021 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x6e, 0xdb, 0x36,
- 0x10, 0xaf, 0x12, 0x27, 0xb6, 0x4e, 0xb1, 0xab, 0x30, 0xed, 0xa2, 0xb6, 0x08, 0x66, 0x18, 0x6b,
- 0x11, 0x0c, 0x6b, 0x5a, 0x64, 0x45, 0x50, 0x04, 0xc5, 0x00, 0xc7, 0x09, 0xb2, 0x2e, 0x48, 0x5c,
- 0x30, 0x7f, 0x56, 0x6c, 0x1f, 0x04, 0x5a, 0xa2, 0x13, 0x75, 0x96, 0x28, 0x90, 0x54, 0x91, 0xf4,
- 0x1d, 0xf6, 0x54, 0x7b, 0x96, 0xbd, 0xc6, 0x30, 0xf0, 0x28, 0xd9, 0xca, 0xe6, 0xad, 0x41, 0xbf,
- 0x89, 0xf7, 0xfb, 0xc3, 0x3b, 0xf2, 0x78, 0x36, 0xb4, 0x53, 0xae, 0x65, 0x12, 0xa9, 0xad, 0x5c,
- 0x0a, 0x2d, 0xc8, 0x9a, 0x12, 0x22, 0xbb, 0x0c, 0x47, 0x45, 0x32, 0x89, 0xc3, 0x12, 0xea, 0xfd,
- 0x05, 0xe0, 0x1d, 0xdb, 0xef, 0x3d, 0xa6, 0x38, 0x79, 0x09, 0x0f, 0x2c, 0x21, 0x66, 0x9a, 0x87,
- 0x3a, 0x49, 0xb9, 0xd2, 0x2c, 0xcd, 0x03, 0xa7, 0xeb, 0x6c, 0x2e, 0x52, 0x82, 0xd8, 0x3e, 0xd3,
- 0xfc, 0xac, 0x42, 0xc8, 0x23, 0x68, 0x59, 0x45, 0x12, 0x07, 0x0b, 0x5d, 0x67, 0xd3, 0xa5, 0x4d,
- 0x5c, 0xbf, 0x8d, 0xc9, 0x2e, 0x3c, 0xca, 0x27, 0x4c, 0x8f, 0x85, 0x4c, 0xc3, 0x8f, 0x5c, 0xaa,
- 0x44, 0x64, 0x61, 0x24, 0x62, 0x9e, 0xb1, 0x94, 0x07, 0x8b, 0xc8, 0x5d, 0xaf, 0x08, 0x17, 0x16,
- 0x1f, 0x94, 0x30, 0x79, 0x0a, 0x1d, 0xcd, 0xe4, 0x25, 0xd7, 0x61, 0x2e, 0x45, 0x5c, 0x44, 0x3a,
- 0x68, 0xa0, 0xa0, 0x6d, 0xa3, 0xef, 0x6c, 0x90, 0xc4, 0xf0, 0xa0, 0xa4, 0xd9, 0x24, 0x3e, 0x32,
- 0x99, 0xb0, 0x4c, 0x07, 0x4b, 0x5d, 0x67, 0xb3, 0xb3, 0xfd, 0x7c, 0x6b, 0x4e, 0xcd, 0x5b, 0xb5,
- 0x7a, 0xb7, 0xf6, 0x0c, 0x72, 0x61, 0x45, 0xbb, 0x8b, 0x07, 0x27, 0x87, 0x94, 0x58, 0xbf, 0x3a,
- 0x40, 0x86, 0xe0, 0x95, 0xbb, 0x30, 0x19, 0x5d, 0x05, 0xcb, 0x68, 0xfe, 0xf4, 0xb3, 0xe6, 0x7d,
- 0x19, 0x5d, 0xed, 0x36, 0xcf, 0x4f, 0x8e, 0x4e, 0x86, 0x3f, 0x9f, 0x50, 0xb0, 0x16, 0x26, 0x48,
- 0xb6, 0x60, 0xad, 0x66, 0x38, 0xcd, 0xba, 0x89, 0x25, 0xae, 0xce, 0x88, 0x55, 0x02, 0xdf, 0x41,
- 0x99, 0x56, 0x18, 0xe5, 0xc5, 0x94, 0xde, 0x42, 0xba, 0x6f, 0x91, 0x41, 0x5e, 0x54, 0xec, 0x23,
- 0x70, 0xaf, 0x84, 0x2a, 0x93, 0x75, 0xbf, 0x28, 0xd9, 0x96, 0x31, 0xc0, 0x54, 0x29, 0xb4, 0xd1,
- 0x6c, 0x3b, 0x8b, 0xad, 0x21, 0x7c, 0x91, 0xa1, 0x67, 0x4c, 0xb6, 0xb3, 0x18, 0x3d, 0xd7, 0xa1,
- 0x89, 0x9e, 0x42, 0x05, 0x1e, 0xd6, 0xb0, 0x6c, 0x96, 0x43, 0x45, 0x7a, 0xe5, 0x66, 0x42, 0x85,
- 0xfc, 0x5a, 0x4b, 0x16, 0xac, 0x20, 0xec, 0x59, 0xf8, 0xc0, 0x84, 0xa6, 0x9c, 0x48, 0x0a, 0xa5,
- 0x8c, 0x45, 0x7b, 0xc6, 0x19, 0x98, 0xd8, 0x50, 0x91, 0x67, 0x70, 0xbf, 0xc6, 0xc1, 0xb4, 0x3b,
- 0xb6, 0x7d, 0xa6, 0x2c, 0x4c, 0xe4, 0x39, 0xac, 0xd5, 0x78, 0xd3, 0x12, 0xef, 0xdb, 0x83, 0x9d,
- 0x72, 0x6b, 0x79, 0x8b, 0x42, 0x87, 0x71, 0x22, 0x03, 0xdf, 0xe6, 0x2d, 0x0a, 0xbd, 0x9f, 0x48,
- 0xf2, 0x03, 0x78, 0x8a, 0xeb, 0x22, 0x0f, 0xb5, 0x10, 0x13, 0x15, 0xac, 0x76, 0x17, 0x37, 0xbd,
- 0xed, 0x8d, 0xb9, 0x47, 0xf4, 0x8e, 0xcb, 0xf1, 0xdb, 0x6c, 0x2c, 0x28, 0xa0, 0xe2, 0xcc, 0x08,
- 0xc8, 0x2e, 0xb8, 0xbf, 0x31, 0x9d, 0x84, 0xb2, 0xc8, 0x54, 0x40, 0xee, 0xa2, 0x6e, 0x19, 0x3e,
- 0x2d, 0x32, 0x45, 0xde, 0x00, 0x58, 0x26, 0x8a, 0xd7, 0xee, 0x22, 0x76, 0x11, 0xad, 0xd4, 0x59,
- 0x92, 0x7d, 0x60, 0x56, 0xfd, 0xe0, 0x4e, 0x6a, 0x14, 0xa0, 0xfa, 0x7b, 0x58, 0xd2, 0x42, 0xb3,
- 0x49, 0xf0, 0xb0, 0xeb, 0x7c, 0x5e, 0x68, 0xb9, 0xe4, 0x02, 0xe6, 0x8d, 0xa2, 0xe0, 0x2b, 0xb4,
- 0x78, 0x36, 0xd7, 0xe2, 0xd4, 0xc4, 0xf0, 0x49, 0x96, 0x1d, 0x46, 0x57, 0xd5, 0x3f, 0x43, 0x64,
- 0x00, 0x2b, 0x56, 0x15, 0x89, 0x6c, 0x9c, 0x5c, 0x06, 0xeb, 0x68, 0xd8, 0x9d, 0x6b, 0x88, 0xc2,
- 0x01, 0xf2, 0xa8, 0x37, 0x9a, 0x2d, 0x7a, 0x2f, 0x61, 0xe5, 0xd6, 0xd3, 0x6f, 0x41, 0xe3, 0xfc,
- 0xf4, 0x80, 0xfa, 0xf7, 0x48, 0x1b, 0x5c, 0xf3, 0xb5, 0x7f, 0xb0, 0x77, 0x7e, 0xe8, 0x3b, 0xa4,
- 0x09, 0x66, 0x5c, 0xf8, 0x0b, 0xbd, 0x37, 0xd0, 0xc0, 0xe6, 0xf0, 0xa0, 0x6a, 0x76, 0xff, 0x9e,
- 0x41, 0xfb, 0xf4, 0xd8, 0x77, 0x88, 0x0b, 0x4b, 0x7d, 0x7a, 0xbc, 0xf3, 0xca, 0x5f, 0x30, 0xb1,
- 0xf7, 0xaf, 0x77, 0xfc, 0x45, 0x02, 0xb0, 0xfc, 0xfe, 0xf5, 0x4e, 0xb8, 0xf3, 0xca, 0x6f, 0xf4,
- 0xfa, 0xe0, 0xd5, 0x72, 0x31, 0xd3, 0xb4, 0x50, 0x3c, 0xbc, 0x14, 0x29, 0xc3, 0x99, 0xdb, 0xa2,
- 0xcd, 0x42, 0xf1, 0x43, 0x91, 0x32, 0xd3, 0x7c, 0x06, 0x92, 0x23, 0x8e, 0x73, 0xb6, 0x45, 0x97,
- 0x0b, 0xc5, 0xe9, 0x88, 0xf7, 0x7e, 0x77, 0xa0, 0x55, 0x9d, 0x31, 0x21, 0xd0, 0x88, 0xb9, 0x8a,
- 0x50, 0xec, 0x52, 0xfc, 0x36, 0x31, 0x1c, 0xb9, 0x76, 0x3c, 0xe3, 0x37, 0xd9, 0x00, 0x50, 0x9a,
- 0x49, 0x8d, 0x33, 0x1e, 0x87, 0x71, 0x83, 0xba, 0x18, 0x31, 0xa3, 0x9d, 0x3c, 0x01, 0x57, 0x72,
- 0x36, 0xb1, 0x68, 0x03, 0xd1, 0x96, 0x09, 0x20, 0xb8, 0x01, 0x90, 0xf2, 0x54, 0xc8, 0x9b, 0xb0,
- 0x50, 0x1c, 0x47, 0x6d, 0x83, 0xba, 0x36, 0x72, 0xae, 0x78, 0xef, 0x4f, 0x07, 0x3a, 0xc7, 0x22,
- 0x2e, 0x26, 0xfc, 0xec, 0x26, 0xe7, 0x98, 0xd5, 0xaf, 0xd5, 0xd5, 0xa8, 0x1b, 0xa5, 0x79, 0x8a,
- 0xd9, 0x75, 0xb6, 0x5f, 0xcc, 0x9f, 0x21, 0xb7, 0xa4, 0xf6, 0xa6, 0x4e, 0x51, 0x56, 0x9b, 0x26,
- 0xa3, 0x59, 0x94, 0x7c, 0x0d, 0x5e, 0x8a, 0x9a, 0x50, 0xdf, 0xe4, 0x55, 0x95, 0x90, 0x4e, 0x6d,
- 0xc8, 0x37, 0xd0, 0xc9, 0x8a, 0x34, 0x14, 0xe3, 0xd0, 0x06, 0x15, 0xd6, 0xdb, 0xa6, 0x2b, 0x59,
- 0x91, 0x0e, 0xc7, 0x76, 0x3f, 0xd5, 0x7b, 0x51, 0xde, 0x44, 0xe9, 0x7a, 0xeb, 0x3a, 0x5d, 0x58,
- 0x3a, 0x1d, 0x0e, 0x4f, 0xcc, 0xbd, 0xb7, 0xa0, 0x71, 0xdc, 0x3f, 0x3a, 0xf0, 0x17, 0x7a, 0x13,
- 0x78, 0x3c, 0x90, 0x89, 0x4e, 0x22, 0x36, 0x39, 0x57, 0x5c, 0xfe, 0x24, 0x0a, 0x99, 0xf1, 0x9b,
- 0xaa, 0x1b, 0xab, 0x43, 0x77, 0x6a, 0x87, 0xbe, 0x0b, 0xcd, 0xaa, 0xdb, 0x17, 0xfe, 0xa7, 0x39,
- 0x6b, 0x53, 0x94, 0x56, 0x82, 0xde, 0x08, 0x9e, 0xcc, 0xd9, 0x4d, 0xcd, 0x9a, 0xbf, 0x11, 0x15,
- 0x1f, 0x54, 0xe0, 0xe0, 0x0b, 0x9e, 0x7f, 0xb2, 0xff, 0x9d, 0x2d, 0x45, 0x71, 0xef, 0x0f, 0x07,
- 0x56, 0xff, 0xf5, 0xd4, 0x48, 0x00, 0xcd, 0xea, 0xdc, 0x1c, 0x3c, 0xb7, 0x6a, 0x49, 0x1e, 0x43,
- 0xab, 0xfc, 0x2d, 0xb2, 0x05, 0xb5, 0xe9, 0x74, 0x4d, 0xbe, 0x85, 0x55, 0x7c, 0xee, 0x21, 0x9b,
- 0x4c, 0x44, 0x14, 0x46, 0xa2, 0xc8, 0x74, 0xd9, 0x67, 0xf7, 0x11, 0xe8, 0x9b, 0xf8, 0xc0, 0x84,
- 0xc9, 0x26, 0xf8, 0x75, 0xae, 0x4a, 0x3e, 0x55, 0x4d, 0xd7, 0x99, 0x51, 0x4f, 0x93, 0x4f, 0xdc,
- 0x0c, 0xff, 0x94, 0x5d, 0x87, 0x57, 0x9c, 0xe5, 0x96, 0x66, 0xbb, 0xcf, 0x4b, 0xd9, 0xf5, 0x8f,
- 0x9c, 0xe5, 0x86, 0xb3, 0xf7, 0xf0, 0x97, 0x72, 0xbe, 0x94, 0x75, 0x87, 0xf8, 0xff, 0xe7, 0xef,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x03, 0x26, 0x59, 0x0f, 0x09, 0x00, 0x00,
+ // 1036 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x4e, 0x1b, 0x47,
+ 0x10, 0xcf, 0x61, 0x83, 0x7d, 0x73, 0xd8, 0x1c, 0x0b, 0x29, 0x97, 0x44, 0xa8, 0x96, 0xd5, 0x44,
+ 0xa8, 0x6a, 0x48, 0x44, 0x23, 0x14, 0xa1, 0xa8, 0x12, 0x18, 0x44, 0x53, 0x04, 0x8e, 0x16, 0x4c,
+ 0xa3, 0xf6, 0xc3, 0x69, 0x7d, 0xb7, 0x86, 0x4b, 0x7d, 0xb7, 0xd6, 0xee, 0x5e, 0x04, 0x79, 0x87,
+ 0x3e, 0x55, 0x9f, 0xa5, 0xaf, 0x51, 0x55, 0x3b, 0x7b, 0x67, 0x1f, 0xad, 0xdb, 0xa0, 0x7c, 0xf3,
+ 0xce, 0xef, 0xcf, 0xce, 0xec, 0xce, 0xce, 0x19, 0x5a, 0x29, 0xd7, 0x32, 0x89, 0xd4, 0xf6, 0x44,
+ 0x0a, 0x2d, 0xc8, 0x9a, 0x12, 0x22, 0xbb, 0x0a, 0x87, 0x79, 0x32, 0x8e, 0xc3, 0x02, 0xea, 0xfe,
+ 0x05, 0xe0, 0x9d, 0xda, 0xdf, 0x07, 0x4c, 0x71, 0xf2, 0x12, 0xd6, 0x2d, 0x21, 0x66, 0x9a, 0x87,
+ 0x3a, 0x49, 0xb9, 0xd2, 0x2c, 0x9d, 0x04, 0x4e, 0xc7, 0xd9, 0xaa, 0x51, 0x82, 0xd8, 0x21, 0xd3,
+ 0xfc, 0xa2, 0x44, 0xc8, 0x23, 0x68, 0x5a, 0x45, 0x12, 0x07, 0x0b, 0x1d, 0x67, 0xcb, 0xa5, 0x0d,
+ 0x5c, 0xbf, 0x8d, 0xc9, 0x1e, 0x3c, 0x9a, 0x8c, 0x99, 0x1e, 0x09, 0x99, 0x86, 0x1f, 0xb9, 0x54,
+ 0x89, 0xc8, 0xc2, 0x48, 0xc4, 0x3c, 0x63, 0x29, 0x0f, 0x6a, 0xc8, 0xdd, 0x28, 0x09, 0x97, 0x16,
+ 0xef, 0x15, 0x30, 0x79, 0x0a, 0x6d, 0xcd, 0xe4, 0x15, 0xd7, 0xe1, 0x44, 0x8a, 0x38, 0x8f, 0x74,
+ 0x50, 0x47, 0x41, 0xcb, 0x46, 0xdf, 0xd9, 0x20, 0x89, 0x61, 0xbd, 0xa0, 0xd9, 0x24, 0x3e, 0x32,
+ 0x99, 0xb0, 0x4c, 0x07, 0x8b, 0x1d, 0x67, 0xab, 0xbd, 0xf3, 0x7c, 0x7b, 0x4e, 0xcd, 0xdb, 0x95,
+ 0x7a, 0xb7, 0x0f, 0x0c, 0x72, 0x69, 0x45, 0x7b, 0xb5, 0xa3, 0xb3, 0x63, 0x4a, 0xac, 0x5f, 0x15,
+ 0x20, 0x7d, 0xf0, 0x8a, 0x5d, 0x98, 0x8c, 0xae, 0x83, 0x25, 0x34, 0x7f, 0xfa, 0x59, 0xf3, 0x7d,
+ 0x19, 0x5d, 0xef, 0x35, 0x06, 0x67, 0x27, 0x67, 0xfd, 0x9f, 0xcf, 0x28, 0x58, 0x0b, 0x13, 0x24,
+ 0xdb, 0xb0, 0x56, 0x31, 0x9c, 0x66, 0xdd, 0xc0, 0x12, 0x57, 0x67, 0xc4, 0x32, 0x81, 0xef, 0xa0,
+ 0x48, 0x2b, 0x8c, 0x26, 0xf9, 0x94, 0xde, 0x44, 0xba, 0x6f, 0x91, 0xde, 0x24, 0x2f, 0xd9, 0x27,
+ 0xe0, 0x5e, 0x0b, 0x55, 0x24, 0xeb, 0x7e, 0x51, 0xb2, 0x4d, 0x63, 0x80, 0xa9, 0x52, 0x68, 0xa1,
+ 0xd9, 0x4e, 0x16, 0x5b, 0x43, 0xf8, 0x22, 0x43, 0xcf, 0x98, 0xec, 0x64, 0x31, 0x7a, 0x6e, 0x40,
+ 0x03, 0x3d, 0x85, 0x0a, 0x3c, 0xac, 0x61, 0xc9, 0x2c, 0xfb, 0x8a, 0x74, 0x8b, 0xcd, 0x84, 0x0a,
+ 0xf9, 0x8d, 0x96, 0x2c, 0x58, 0x46, 0xd8, 0xb3, 0xf0, 0x91, 0x09, 0x4d, 0x39, 0x91, 0x14, 0x4a,
+ 0x19, 0x8b, 0xd6, 0x8c, 0xd3, 0x33, 0xb1, 0xbe, 0x22, 0xcf, 0x60, 0xa5, 0xc2, 0xc1, 0xb4, 0xdb,
+ 0xb6, 0x7d, 0xa6, 0x2c, 0x4c, 0xe4, 0x39, 0xac, 0x55, 0x78, 0xd3, 0x12, 0x57, 0xec, 0xc1, 0x4e,
+ 0xb9, 0x95, 0xbc, 0x45, 0xae, 0xc3, 0x38, 0x91, 0x81, 0x6f, 0xf3, 0x16, 0xb9, 0x3e, 0x4c, 0x24,
+ 0xf9, 0x01, 0x3c, 0xc5, 0x75, 0x3e, 0x09, 0xb5, 0x10, 0x63, 0x15, 0xac, 0x76, 0x6a, 0x5b, 0xde,
+ 0xce, 0xe6, 0xdc, 0x23, 0x7a, 0xc7, 0xe5, 0xe8, 0x6d, 0x36, 0x12, 0x14, 0x50, 0x71, 0x61, 0x04,
+ 0x64, 0x0f, 0xdc, 0xdf, 0x98, 0x4e, 0x42, 0x99, 0x67, 0x2a, 0x20, 0xf7, 0x51, 0x37, 0x0d, 0x9f,
+ 0xe6, 0x99, 0x22, 0x6f, 0x00, 0x2c, 0x13, 0xc5, 0x6b, 0xf7, 0x11, 0xbb, 0x88, 0x96, 0xea, 0x2c,
+ 0xc9, 0x3e, 0x30, 0xab, 0x5e, 0xbf, 0x97, 0x1a, 0x05, 0xa8, 0xfe, 0x1e, 0x16, 0xb5, 0xd0, 0x6c,
+ 0x1c, 0x3c, 0xec, 0x38, 0x9f, 0x17, 0x5a, 0x2e, 0xb9, 0x84, 0x79, 0xa3, 0x28, 0xf8, 0x0a, 0x2d,
+ 0x9e, 0xcd, 0xb5, 0x38, 0x37, 0x31, 0x7c, 0x92, 0x45, 0x87, 0xd1, 0x55, 0xf5, 0xcf, 0x10, 0xe9,
+ 0xc1, 0xb2, 0x55, 0x45, 0x22, 0x1b, 0x25, 0x57, 0xc1, 0x06, 0x1a, 0x76, 0xe6, 0x1a, 0xa2, 0xb0,
+ 0x87, 0x3c, 0xea, 0x0d, 0x67, 0x8b, 0xee, 0x4b, 0x58, 0xbe, 0xf3, 0xf4, 0x9b, 0x50, 0x1f, 0x9c,
+ 0x1f, 0x51, 0xff, 0x01, 0x69, 0x81, 0x6b, 0x7e, 0x1d, 0x1e, 0x1d, 0x0c, 0x8e, 0x7d, 0x87, 0x34,
+ 0xc0, 0x8c, 0x0b, 0x7f, 0xa1, 0xfb, 0x06, 0xea, 0xd8, 0x1c, 0x1e, 0x94, 0xcd, 0xee, 0x3f, 0x30,
+ 0xe8, 0x3e, 0x3d, 0xf5, 0x1d, 0xe2, 0xc2, 0xe2, 0x3e, 0x3d, 0xdd, 0x7d, 0xe5, 0x2f, 0x98, 0xd8,
+ 0xfb, 0xd7, 0xbb, 0x7e, 0x8d, 0x00, 0x2c, 0xbd, 0x7f, 0xbd, 0x1b, 0xee, 0xbe, 0xf2, 0xeb, 0xdd,
+ 0x2b, 0xf0, 0x2a, 0xb9, 0x98, 0x69, 0x9a, 0x2b, 0x1e, 0x5e, 0x89, 0x94, 0xe1, 0xcc, 0x6d, 0xd2,
+ 0x46, 0xae, 0xf8, 0xb1, 0x48, 0x99, 0x69, 0x3e, 0x03, 0xc9, 0x21, 0xc7, 0x39, 0xdb, 0xa4, 0x4b,
+ 0xb9, 0xe2, 0x74, 0xc8, 0xc9, 0x37, 0xd0, 0x1e, 0x09, 0x19, 0xf1, 0x70, 0xaa, 0xac, 0x21, 0xbe,
+ 0x8c, 0xd1, 0x81, 0x95, 0x77, 0x7f, 0x77, 0xa0, 0x59, 0xde, 0x04, 0x21, 0x50, 0x8f, 0xb9, 0x8a,
+ 0x70, 0x0b, 0x97, 0xe2, 0x6f, 0x13, 0xc3, 0xc1, 0x6c, 0x87, 0x38, 0xfe, 0x26, 0x9b, 0x00, 0x4a,
+ 0x33, 0xa9, 0xf1, 0x4b, 0x80, 0xb6, 0x75, 0xea, 0x62, 0xc4, 0x7c, 0x00, 0xc8, 0x13, 0x70, 0x25,
+ 0x67, 0x63, 0x8b, 0xd6, 0x11, 0x6d, 0x9a, 0x00, 0x82, 0x9b, 0x00, 0x29, 0x4f, 0x85, 0xbc, 0x35,
+ 0x79, 0xe1, 0x40, 0xae, 0x53, 0xd7, 0x46, 0x06, 0x8a, 0x77, 0xff, 0x74, 0xa0, 0x7d, 0x2a, 0xe2,
+ 0x7c, 0xcc, 0x2f, 0x6e, 0x27, 0x1c, 0xb3, 0xfa, 0xb5, 0xbc, 0x40, 0x75, 0xab, 0x34, 0x4f, 0x31,
+ 0xbb, 0xf6, 0xce, 0x8b, 0xf9, 0x93, 0xe6, 0x8e, 0xd4, 0xde, 0xe7, 0x39, 0xca, 0x2a, 0x33, 0x67,
+ 0x38, 0x8b, 0x92, 0xaf, 0xc1, 0x4b, 0x51, 0x13, 0xea, 0xdb, 0x49, 0x59, 0x25, 0xa4, 0x53, 0x1b,
+ 0x73, 0x8c, 0x59, 0x9e, 0x86, 0x62, 0x14, 0xda, 0xa0, 0xc2, 0x7a, 0x5b, 0x74, 0x39, 0xcb, 0xd3,
+ 0xfe, 0xc8, 0xee, 0xa7, 0xba, 0x2f, 0x8a, 0xfb, 0x2a, 0x5c, 0xef, 0x5c, 0xba, 0x0b, 0x8b, 0xe7,
+ 0xfd, 0xfe, 0x99, 0xe9, 0x8e, 0x26, 0xd4, 0x4f, 0xf7, 0x4f, 0x8e, 0xfc, 0x85, 0xee, 0x18, 0x1e,
+ 0xf7, 0x64, 0xa2, 0x93, 0x88, 0x8d, 0x07, 0x8a, 0xcb, 0x9f, 0x44, 0x2e, 0x33, 0x7e, 0x5b, 0xf6,
+ 0x6c, 0x79, 0xe8, 0x4e, 0xe5, 0xd0, 0xf7, 0xa0, 0x51, 0xbe, 0x89, 0x85, 0xff, 0x69, 0xe1, 0xca,
+ 0xac, 0xa5, 0xa5, 0xa0, 0x3b, 0x84, 0x27, 0x73, 0x76, 0x53, 0xb3, 0x27, 0x52, 0x8f, 0xf2, 0x0f,
+ 0x2a, 0x70, 0xf0, 0x9d, 0xcf, 0x3f, 0xd9, 0xff, 0xce, 0x96, 0xa2, 0xb8, 0xfb, 0x87, 0x03, 0xab,
+ 0xff, 0x7a, 0x90, 0x24, 0x80, 0x46, 0x79, 0x6e, 0x0e, 0x9e, 0x5b, 0xb9, 0x24, 0x8f, 0xa1, 0x59,
+ 0x7c, 0xb1, 0x6c, 0x41, 0x2d, 0x3a, 0x5d, 0x93, 0x6f, 0x61, 0x15, 0x87, 0x42, 0xc8, 0xc6, 0x63,
+ 0x11, 0x85, 0x91, 0xc8, 0x33, 0x5d, 0xf4, 0xd9, 0x0a, 0x02, 0xfb, 0x26, 0xde, 0x33, 0x61, 0xb2,
+ 0x05, 0x7e, 0x95, 0xab, 0x92, 0x4f, 0x65, 0xd3, 0xb5, 0x67, 0xd4, 0xf3, 0xe4, 0x13, 0x37, 0x9f,
+ 0x88, 0x94, 0xdd, 0x84, 0xd7, 0x9c, 0x4d, 0x2c, 0xcd, 0x76, 0x9f, 0x97, 0xb2, 0x9b, 0x1f, 0x39,
+ 0x9b, 0x18, 0xce, 0xc1, 0xc3, 0x5f, 0x8a, 0x29, 0x54, 0xd4, 0x1d, 0xe2, 0xbf, 0xa4, 0xbf, 0x03,
+ 0x00, 0x00, 0xff, 0xff, 0x85, 0xc5, 0xe0, 0x4b, 0x35, 0x09, 0x00, 0x00,
}
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 6559ba3..4d6118b 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -102,6 +102,8 @@
optional bool use_goma = 1;
optional bool use_rbe = 2;
+
+ optional bool force_use_goma = 3;
}
message PerfInfo {