Merge "Remove obsolete dexpreopt config option `UseArtImage`."
diff --git a/Android.bp b/Android.bp
index 42a8e5c..63de015 100644
--- a/Android.bp
+++ b/Android.bp
@@ -119,3 +119,14 @@
dexpreopt_systemserver_check {
name: "dexpreopt_systemserver_check",
}
+
+// buildinfo.prop contains common properties for system/build.prop, like ro.build.version.*
+buildinfo_prop {
+ name: "buildinfo.prop",
+
+ // not installable because this will be included to system/build.prop
+ installable: false,
+
+ // Currently, only microdroid can refer to buildinfo.prop
+ visibility: ["//packages/modules/Virtualization/microdroid"],
+}
diff --git a/OWNERS b/OWNERS
index 0cfb241..0662016 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,12 +2,13 @@
# approving build related projects.
# AMER
-ahumesky@google.com
+agespino@google.com
alexmarquez@google.com
asmundak@google.com
ccross@android.com
colefaust@google.com
cparsons@google.com
+dacek@google.com
delmerico@google.com
dwillemsen@google.com
eakammer@google.com
@@ -17,13 +18,12 @@
spandandas@google.com
tradical@google.com
usta@google.com
+vinhdaitran@google.com
weiwli@google.com
yudiliu@google.com
-yuntaoxu@google.com
# APAC
jingwen@google.com
-ruperts@google.com
# EMEA
hansson@google.com
diff --git a/android/Android.bp b/android/Android.bp
index 87b021f..d583703 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -36,6 +36,7 @@
"bazel.go",
"bazel_handler.go",
"bazel_paths.go",
+ "buildinfo_prop.go",
"config.go",
"config_bp2build.go",
"csuite_config.go",
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 72961e6..26cfd57 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -313,6 +313,7 @@
"host_bionic_linker_asm", // depends on extract_linker, a go binary.
"host_bionic_linker_script", // depends on extract_linker, a go binary.
"libc_musl_sysroot_bionic_arch_headers", // depends on soong_zip
+ "libc_musl_sysroot_zlib_headers", // depends on soong_zip and zip2zip
"libc_musl_sysroot_bionic_headers", // 218405924, depends on soong_zip and generates duplicate srcs
"libc_musl_sysroot_libc++_headers", "libc_musl_sysroot_libc++abi_headers", // depends on soong_zip, zip2zip
"robolectric-sqlite4java-native", // depends on soong_zip, a go binary
@@ -367,6 +368,10 @@
"timezone-host", // depends on unconverted modules: art.module.api.annotations
"truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
"truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
+
+ // b/215723302; awaiting tz{data,_version} to then rename targets conflicting with srcs
+ "tzdata",
+ "tz_version",
}
Bp2buildCcLibraryStaticOnlyList = []string{}
diff --git a/android/androidmk.go b/android/androidmk.go
index e9c63fb..5c715b4 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -578,7 +578,7 @@
}
}
- if !base.InRamdisk() && !base.InVendorRamdisk() {
+ if !base.InVendorRamdisk() {
a.AddPaths("LOCAL_FULL_INIT_RC", base.initRcPaths)
}
if len(base.vintfFragmentsPaths) > 0 {
diff --git a/android/api_levels.go b/android/api_levels.go
index 8163894..aa55aa1 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -54,6 +54,14 @@
isPreview bool
}
+func (this ApiLevel) FinalInt() int {
+ if this.IsPreview() {
+ panic("Requested a final int from a non-final ApiLevel")
+ } else {
+ return this.number
+ }
+}
+
func (this ApiLevel) FinalOrFutureInt() int {
if this.IsPreview() {
return FutureApiLevelInt
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index d851a98..6b2be69 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -853,7 +853,8 @@
// build statement have later timestamps than the outputs.
rule.Restat()
- rule.Build(fmt.Sprintf("bazel %d", index), buildStatement.Mnemonic)
+ desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
+ rule.Build(fmt.Sprintf("bazel %d", index), desc)
}
}
diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go
new file mode 100644
index 0000000..6339a71
--- /dev/null
+++ b/android/buildinfo_prop.go
@@ -0,0 +1,182 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ ctx := InitRegistrationContext
+ ctx.RegisterSingletonModuleType("buildinfo_prop", buildinfoPropFactory)
+}
+
+type buildinfoPropProperties struct {
+ // Whether this module is directly installable to one of the partitions. Default: true.
+ Installable *bool
+}
+
+type buildinfoPropModule struct {
+ SingletonModuleBase
+
+ properties buildinfoPropProperties
+
+ outputFilePath OutputPath
+ installPath InstallPath
+}
+
+var _ OutputFileProducer = (*buildinfoPropModule)(nil)
+
+func (p *buildinfoPropModule) installable() bool {
+ return proptools.BoolDefault(p.properties.Installable, true)
+}
+
+// OutputFileProducer
+func (p *buildinfoPropModule) OutputFiles(tag string) (Paths, error) {
+ if tag != "" {
+ return nil, fmt.Errorf("unsupported tag %q", tag)
+ }
+ return Paths{p.outputFilePath}, nil
+}
+
+func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath
+ if !ctx.Config().KatiEnabled() {
+ WriteFileRule(ctx, p.outputFilePath, "# no buildinfo.prop if kati is disabled")
+ return
+ }
+
+ rule := NewRuleBuilder(pctx, ctx)
+ cmd := rule.Command().Text("(")
+
+ writeString := func(str string) {
+ cmd.Text(`echo "` + str + `" && `)
+ }
+
+ writeString("# begin build properties")
+ writeString("# autogenerated by build/soong/android/buildinfo_prop.go")
+
+ writeProp := func(key, value string) {
+ if strings.Contains(key, "=") {
+ panic(fmt.Errorf("wrong property key %q: key must not contain '='", key))
+ }
+ writeString(key + "=" + value)
+ }
+
+ config := ctx.Config()
+
+ writeProp("ro.build.version.sdk", config.PlatformSdkVersion().String())
+ writeProp("ro.build.version.preview_sdk", config.PlatformPreviewSdkVersion())
+ writeProp("ro.build.version.codename", config.PlatformSdkCodename())
+ writeProp("ro.build.version.all_codenames", strings.Join(config.PlatformVersionActiveCodenames(), ","))
+ writeProp("ro.build.version.release", config.PlatformVersionLastStable())
+ writeProp("ro.build.version.release_or_codename", config.PlatformVersionName())
+ writeProp("ro.build.version.security_patch", config.PlatformSecurityPatch())
+ writeProp("ro.build.version.base_os", config.PlatformBaseOS())
+ writeProp("ro.build.version.min_supported_target_sdk", config.PlatformMinSupportedTargetSdkVersion())
+
+ if config.Eng() {
+ writeProp("ro.build.type", "eng")
+ } else if config.Debuggable() {
+ writeProp("ro.build.type", "userdebug")
+ } else {
+ writeProp("ro.build.type", "user")
+ }
+
+ // Currently, only a few properties are implemented to unblock microdroid use case.
+ // TODO(b/189164487): support below properties as well and replace build/make/tools/buildinfo.sh
+ /*
+ if $BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT {
+ writeProp("ro.build.legacy.id", config.BuildID())
+ } else {
+ writeProp("ro.build.id", config.BuildId())
+ }
+ writeProp("ro.build.display.id", $BUILD_DISPLAY_ID)
+ writeProp("ro.build.version.incremental", $BUILD_NUMBER)
+ writeProp("ro.build.version.preview_sdk_fingerprint", $PLATFORM_PREVIEW_SDK_FINGERPRINT)
+ writeProp("ro.build.version.known_codenames", $PLATFORM_VERSION_KNOWN_CODENAMES)
+ writeProp("ro.build.version.release_or_preview_display", $PLATFORM_DISPLAY_VERSION)
+ writeProp("ro.build.date", `$DATE`)
+ writeProp("ro.build.date.utc", `$DATE +%s`)
+ writeProp("ro.build.user", $BUILD_USERNAME)
+ writeProp("ro.build.host", $BUILD_HOSTNAME)
+ writeProp("ro.build.tags", $BUILD_VERSION_TAGS)
+ writeProp("ro.build.flavor", $TARGET_BUILD_FLAVOR)
+ // These values are deprecated, use "ro.product.cpu.abilist"
+ // instead (see below).
+ writeString("# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
+ writeString("# use ro.product.cpu.abilist instead.")
+ writeProp("ro.product.cpu.abi", $TARGET_CPU_ABI)
+ if [ -n "$TARGET_CPU_ABI2" ] {
+ writeProp("ro.product.cpu.abi2", $TARGET_CPU_ABI2)
+ }
+
+ if [ -n "$PRODUCT_DEFAULT_LOCALE" ] {
+ writeProp("ro.product.locale", $PRODUCT_DEFAULT_LOCALE)
+ }
+ writeProp("ro.wifi.channels", $PRODUCT_DEFAULT_WIFI_CHANNELS)
+ writeString("# ro.build.product is obsolete; use ro.product.device")
+ writeProp("ro.build.product", $TARGET_DEVICE)
+
+ writeString("# Do not try to parse description or thumbprint")
+ writeProp("ro.build.description", $PRIVATE_BUILD_DESC)
+ if [ -n "$BUILD_THUMBPRINT" ] {
+ writeProp("ro.build.thumbprint", $BUILD_THUMBPRINT)
+ }
+ */
+
+ writeString("# end build properties")
+
+ cmd.Text("true) > ").Output(p.outputFilePath)
+ rule.Build("build.prop", "generating build.prop")
+
+ if !p.installable() {
+ p.SkipInstall()
+ }
+
+ p.installPath = PathForModuleInstall(ctx)
+ ctx.InstallFile(p.installPath, p.Name(), p.outputFilePath)
+}
+
+func (f *buildinfoPropModule) GenerateSingletonBuildActions(ctx SingletonContext) {
+ // does nothing; buildinfo_prop is a singeton because two buildinfo modules don't make sense.
+}
+
+func (p *buildinfoPropModule) AndroidMkEntries() []AndroidMkEntries {
+ return []AndroidMkEntries{AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: OptionalPathForPath(p.outputFilePath),
+ ExtraEntries: []AndroidMkExtraEntriesFunc{
+ func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", p.installPath.String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
+ },
+ },
+ }}
+}
+
+// buildinfo_prop module generates a build.prop file, which contains a set of common
+// system/build.prop properties, such as ro.build.version.*. Not all properties are implemented;
+// currently this module is only for microdroid.
+func buildinfoPropFactory() SingletonModule {
+ module := &buildinfoPropModule{}
+ module.AddProperties(&module.properties)
+ InitAndroidModule(module)
+ return module
+}
diff --git a/android/config.go b/android/config.go
index cb2fc61..250c312 100644
--- a/android/config.go
+++ b/android/config.go
@@ -777,8 +777,12 @@
return String(c.productVariables.Platform_base_os)
}
+func (c *config) PlatformVersionLastStable() string {
+ return String(c.productVariables.Platform_version_last_stable)
+}
+
func (c *config) MinSupportedSdkVersion() ApiLevel {
- return uncheckedFinalApiLevel(16)
+ return uncheckedFinalApiLevel(19)
}
func (c *config) FinalApiLevels() []ApiLevel {
diff --git a/android/hooks.go b/android/hooks.go
index 5e3a4a7..2ad3b5f 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -89,8 +89,17 @@
l.appendPrependHelper(props, proptools.PrependMatchingProperties)
}
-func (l *loadHookContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
- inherited := []interface{}{&l.Module().base().commonProperties}
+func (l *loadHookContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) blueprint.Module {
+ return l.bp.CreateModule(factory, name, props...)
+}
+
+type createModuleContext interface {
+ Module() Module
+ createModule(blueprint.ModuleFactory, string, ...interface{}) blueprint.Module
+}
+
+func createModule(ctx createModuleContext, factory ModuleFactory, ext string, props ...interface{}) Module {
+ inherited := []interface{}{&ctx.Module().base().commonProperties}
var typeName string
if typeNameLookup, ok := ModuleTypeByFactory()[reflect.ValueOf(factory)]; ok {
@@ -101,12 +110,12 @@
filePath, _ := factoryFunc.FileLine(factoryPtr)
typeName = fmt.Sprintf("%s_%s", path.Base(filePath), factoryFunc.Name())
}
- typeName = typeName + "_loadHookModule"
+ typeName = typeName + "_" + ext
- module := l.bp.CreateModule(ModuleFactoryAdaptor(factory), typeName, append(inherited, props...)...).(Module)
+ module := ctx.createModule(ModuleFactoryAdaptor(factory), typeName, append(inherited, props...)...).(Module)
- if l.Module().base().variableProperties != nil && module.base().variableProperties != nil {
- src := l.Module().base().variableProperties
+ if ctx.Module().base().variableProperties != nil && module.base().variableProperties != nil {
+ src := ctx.Module().base().variableProperties
dst := []interface{}{
module.base().variableProperties,
// Put an empty copy of the src properties into dst so that properties in src that are not in dst
@@ -122,6 +131,10 @@
return module
}
+func (l *loadHookContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
+ return createModule(l, factory, "_loadHookModule", props...)
+}
+
func (l *loadHookContext) registerScopedModuleType(name string, factory blueprint.ModuleFactory) {
l.bp.RegisterScopedModuleType(name, factory)
}
diff --git a/android/mutator.go b/android/mutator.go
index 739e4ee..02a6143 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,12 +15,9 @@
package android
import (
- "reflect"
-
"android/soong/bazel"
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
// Phases:
@@ -553,29 +550,16 @@
t.Module().base().commonProperties.DebugName = name
}
+func (t *topDownMutatorContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) blueprint.Module {
+ return t.bp.CreateModule(factory, name, props...)
+}
+
func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
- inherited := []interface{}{&t.Module().base().commonProperties}
- module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), append(inherited, props...)...).(Module)
-
- if t.Module().base().variableProperties != nil && module.base().variableProperties != nil {
- src := t.Module().base().variableProperties
- dst := []interface{}{
- module.base().variableProperties,
- // Put an empty copy of the src properties into dst so that properties in src that are not in dst
- // don't cause a "failed to find property to extend" error.
- proptools.CloneEmptyProperties(reflect.ValueOf(src)).Interface(),
- }
- err := proptools.AppendMatchingProperties(dst, src, nil)
- if err != nil {
- panic(err)
- }
- }
-
- return module
+ return createModule(t, factory, "_topDownMutatorModule", props...)
}
func (t *topDownMutatorContext) createModuleWithoutInheritance(factory ModuleFactory, props ...interface{}) Module {
- module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), props...).(Module)
+ module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), "", props...).(Module)
return module
}
diff --git a/android/variable.go b/android/variable.go
index 077b810..373891a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -199,6 +199,7 @@
Platform_preview_sdk_version *string `json:",omitempty"`
Platform_min_supported_target_sdk_version *string `json:",omitempty"`
Platform_base_os *string `json:",omitempty"`
+ Platform_version_last_stable *string `json:",omitempty"`
DeviceName *string `json:",omitempty"`
DeviceProduct *string `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index a7b0a4f..76af1b8 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1656,13 +1656,20 @@
var _ androidApp = (*java.AndroidApp)(nil)
var _ androidApp = (*java.AndroidAppImport)(nil)
+const APEX_VERSION_PLACEHOLDER = "__APEX_VERSION_PLACEHOLDER__"
+
func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) apexFile {
appDir := "app"
if aapp.Privileged() {
appDir = "priv-app"
}
- dirInApex := filepath.Join(appDir, aapp.InstallApkName())
+
+ // TODO(b/224589412, b/226559955): Ensure that the subdirname is suffixed
+ // so that PackageManager correctly invalidates the existing installed apk
+ // in favour of the new APK-in-APEX. See bugs for more information.
+ dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+APEX_VERSION_PLACEHOLDER)
fileToCopy := aapp.OutputFile()
+
af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
af.lintDepSets = aapp.LintDepSets()
@@ -1895,8 +1902,12 @@
if ap.Privileged() {
appDir = "priv-app"
}
- af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(),
- filepath.Join(appDir, ap.BaseModuleName()), appSet, ap)
+ // TODO(b/224589412, b/226559955): Ensure that the dirname is
+ // suffixed so that PackageManager correctly invalidates the
+ // existing installed apk in favour of the new APK-in-APEX.
+ // See bugs for more information.
+ appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+APEX_VERSION_PLACEHOLDER)
+ af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
af.certificate = java.PresignedCertificate
filesInfo = append(filesInfo, af)
} else {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 77cbb58..4a52115 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -682,7 +682,7 @@
"etc/myetc",
"javalib/myjar.jar",
"lib64/mylib.so",
- "app/AppFoo/AppFoo.apk",
+ "app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFoo.apk",
"overlay/blue/rro.apk",
"etc/bpf/bpf.o",
"etc/bpf/bpf2.o",
@@ -5682,8 +5682,8 @@
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
- ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
+ ensureContains(t, copyCmds, "image.apex/app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFoo.apk")
+ ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv@__APEX_VERSION_PLACEHOLDER__/AppFooPriv.apk")
appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
// JNI libraries are uncompressed
@@ -5745,8 +5745,8 @@
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt/AppFooPrebuilt.apk")
- ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AwesomePrebuiltAppFooPriv.apk")
+ ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt@__APEX_VERSION_PLACEHOLDER__/AppFooPrebuilt.apk")
+ ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt@__APEX_VERSION_PLACEHOLDER__/AwesomePrebuiltAppFooPriv.apk")
}
func TestApexWithAppImportsPrefer(t *testing.T) {
@@ -5787,7 +5787,7 @@
}))
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
- "app/AppFoo/AppFooPrebuilt.apk",
+ "app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFooPrebuilt.apk",
})
}
@@ -5820,7 +5820,7 @@
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo/TesterHelpAppFoo.apk")
+ ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo@__APEX_VERSION_PLACEHOLDER__/TesterHelpAppFoo.apk")
}
func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
@@ -6263,8 +6263,8 @@
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
- ensureNotContains(t, copyCmds, "image.apex/app/app/app.apk")
- ensureContains(t, copyCmds, "image.apex/app/override_app/override_app.apk")
+ ensureNotContains(t, copyCmds, "image.apex/app/app@__APEX_VERSION_PLACEHOLDER__/app.apk")
+ ensureContains(t, copyCmds, "image.apex/app/override_app@__APEX_VERSION_PLACEHOLDER__/override_app.apk")
ensureNotContains(t, copyCmds, "image.apex/etc/bpf/bpf.o")
ensureContains(t, copyCmds, "image.apex/etc/bpf/override_bpf.o")
@@ -7168,7 +7168,7 @@
content := bundleConfigRule.Args["content"]
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
- ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo/AppFoo.apk"}]}`)
+ ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFoo.apk"}]}`)
}
func TestAppSetBundle(t *testing.T) {
@@ -7199,9 +7199,9 @@
if len(copyCmds) != 3 {
t.Fatalf("Expected 3 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet$")
- ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet$")
- ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet .*/AppSet.zip$")
+ ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet@__APEX_VERSION_PLACEHOLDER__$")
+ ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet@__APEX_VERSION_PLACEHOLDER__$")
+ ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet@__APEX_VERSION_PLACEHOLDER__ .*/AppSet.zip$")
}
func TestAppSetBundlePrebuilt(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 293f388..d4765d0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -107,14 +107,16 @@
`--canned_fs_config ${canned_fs_config} ` +
`--include_build_info ` +
`--payload_type image ` +
- `--key ${key} ${opt_flags} ${image_dir} ${out} `,
+ `--key ${key} ` +
+ `--apex_version_placeholder ${apex_version_placeholder} ` +
+ `${opt_flags} ${image_dir} ${out} `,
CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
"${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", "${sload_f2fs}", "${make_erofs}",
"${soong_zip}", "${zipalign}", "${aapt2}", "prebuilts/sdk/current/public/android.jar"},
Rspfile: "${out}.copy_commands",
RspfileContent: "${copy_commands}",
Description: "APEX ${image_dir} => ${out}",
- }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type")
+ }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type", "apex_version_placeholder")
zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
@@ -122,12 +124,13 @@
`APEXER_TOOL_PATH=${tool_path} ` +
`${apexer} --force --manifest ${manifest} ` +
`--payload_type zip ` +
+ `--apex_version_placeholder ${apex_version_placeholder} ` +
`${image_dir} ${out} `,
CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
Rspfile: "${out}.copy_commands",
RspfileContent: "${copy_commands}",
Description: "ZipAPEX ${image_dir} => ${out}",
- }, "tool_path", "image_dir", "copy_commands", "manifest")
+ }, "tool_path", "image_dir", "copy_commands", "manifest", "apex_version_placeholder")
apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
blueprint.RuleParams{
@@ -388,7 +391,7 @@
imageDir := android.PathForModuleOut(ctx, "image"+suffix)
- installSymbolFiles := !ctx.Config().KatiEnabled() || a.ExportedToMake()
+ installSymbolFiles := (!ctx.Config().KatiEnabled() || a.ExportedToMake()) && a.installable()
// b/140136207. When there are overriding APEXes for a VNDK APEX, the symbols file for the overridden
// APEX and the overriding APEX will have the same installation paths at /apex/com.android.vndk.v<ver>
@@ -658,14 +661,15 @@
Output: unsignedOutputFile,
Description: "apex (" + apexType.name() + ")",
Args: map[string]string{
- "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
- "image_dir": imageDir.String(),
- "copy_commands": strings.Join(copyCommands, " && "),
- "manifest": a.manifestPbOut.String(),
- "file_contexts": fileContexts.String(),
- "canned_fs_config": cannedFsConfig.String(),
- "key": a.privateKeyFile.String(),
- "opt_flags": strings.Join(optFlags, " "),
+ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+ "image_dir": imageDir.String(),
+ "copy_commands": strings.Join(copyCommands, " && "),
+ "manifest": a.manifestPbOut.String(),
+ "file_contexts": fileContexts.String(),
+ "canned_fs_config": cannedFsConfig.String(),
+ "key": a.privateKeyFile.String(),
+ "opt_flags": strings.Join(optFlags, " "),
+ "apex_version_placeholder": APEX_VERSION_PLACEHOLDER,
},
})
@@ -757,10 +761,11 @@
Output: unsignedOutputFile,
Description: "apex (" + apexType.name() + ")",
Args: map[string]string{
- "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
- "image_dir": imageDir.String(),
- "copy_commands": strings.Join(copyCommands, " && "),
- "manifest": a.manifestPbOut.String(),
+ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+ "image_dir": imageDir.String(),
+ "copy_commands": strings.Join(copyCommands, " && "),
+ "manifest": a.manifestPbOut.String(),
+ "apex_version_placeholder": APEX_VERSION_PLACEHOLDER,
},
})
}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 8f78968..e0ce194 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -45,7 +45,9 @@
"cc_library_shared_conversion_test.go",
"cc_library_static_conversion_test.go",
"cc_object_conversion_test.go",
+ "cc_prebuilt_library_conversion_test.go",
"cc_prebuilt_library_shared_test.go",
+ "cc_prebuilt_library_static_test.go",
"conversion_test.go",
"filegroup_conversion_test.go",
"genrule_conversion_test.go",
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 22c9dfe..7c2c100 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -176,8 +176,8 @@
":whole_static_lib_1",
":whole_static_lib_2",
]`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
+ "sdk_version": `"current"`,
+ "min_sdk_version": `"29"`,
}),
},
})
@@ -496,3 +496,27 @@
},
)
}
+
+func TestCcLibrarySharedSystemSharedLibsSharedEmpty(t *testing.T) {
+ runCcLibrarySharedTestCase(t, bp2buildTestCase{
+ description: "cc_library_shared system_shared_libs empty shared default",
+ moduleTypeUnderTest: "cc_library_shared",
+ moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
+ blueprint: soongCcLibrarySharedPreamble + `
+cc_defaults {
+ name: "empty_defaults",
+ shared: {
+ system_shared_libs: [],
+ },
+ include_build_directory: false,
+}
+cc_library_shared {
+ name: "empty",
+ defaults: ["empty_defaults"],
+}
+`,
+ expectedBazelTargets: []string{makeBazelTarget("cc_library_shared", "empty", attrNameToString{
+ "system_dynamic_deps": "[]",
+ })},
+ })
+}
diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go
index 8183316..3cf8969 100644
--- a/bp2build/cc_prebuilt_library_conversion_test.go
+++ b/bp2build/cc_prebuilt_library_conversion_test.go
@@ -136,7 +136,7 @@
},
bazel_module: { bp2build_available: true },
}`,
- expectedErr: fmt.Errorf("Expected at most once source file"),
+ expectedErr: fmt.Errorf("Expected at most one source file"),
})
}
@@ -159,7 +159,7 @@
},
bazel_module: { bp2build_available: true },
}`,
- expectedErr: fmt.Errorf("Expected at most once source file"),
+ expectedErr: fmt.Errorf("Expected at most one source file"),
})
}
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index 3a5d5bb..2e4b221 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -45,11 +45,11 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("prebuilt_etc", "apex_tz_version", attrNameToString{
+ makeBazelTarget("prebuilt_file", "apex_tz_version", attrNameToString{
"filename": `"tz_version"`,
"installable": `False`,
"src": `"version/tz_version"`,
- "sub_dir": `"tz"`,
+ "dir": `"etc/tz"`,
})}})
}
@@ -75,7 +75,7 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("prebuilt_etc", "apex_tz_version", attrNameToString{
+ makeBazelTarget("prebuilt_file", "apex_tz_version", attrNameToString{
"filename": `"tz_version"`,
"installable": `False`,
"src": `select({
@@ -83,7 +83,7 @@
"//build/bazel/platforms/arch:arm64": "arm64",
"//conditions:default": "version/tz_version",
})`,
- "sub_dir": `"tz"`,
+ "dir": `"etc/tz"`,
})}})
}
@@ -114,7 +114,7 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("prebuilt_etc", "apex_tz_version", attrNameToString{
+ makeBazelTarget("prebuilt_file", "apex_tz_version", attrNameToString{
"filename": `"tz_version"`,
"installable": `False`,
"src": `select({
@@ -125,6 +125,59 @@
"//build/bazel/platforms/os_arch:linux_bionic_arm64": "darwin_or_arm64",
"//conditions:default": "version/tz_version",
})`,
- "sub_dir": `"tz"`,
+ "dir": `"etc/tz"`,
+ })}})
+}
+
+func runPrebuiltUsrShareTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ (&tc).moduleTypeUnderTest = "prebuilt_usr_share"
+ (&tc).moduleTypeUnderTestFactory = etc.PrebuiltUserShareFactory
+ runBp2BuildTestCase(t, registerPrebuiltEtcModuleTypes, tc)
+}
+
+func registerPrebuiltUsrShareModuleTypes(ctx android.RegistrationContext) {
+}
+
+func TestPrebuiltUsrShareSimple(t *testing.T) {
+ runPrebuiltUsrShareTestCase(t, bp2buildTestCase{
+ description: "prebuilt_usr_share - simple example",
+ filesystem: map[string]string{},
+ blueprint: `
+prebuilt_usr_share {
+ name: "apex_tz_version",
+ src: "version/tz_version",
+ filename: "tz_version",
+ sub_dir: "tz",
+ installable: false,
+}
+`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("prebuilt_file", "apex_tz_version", attrNameToString{
+ "filename": `"tz_version"`,
+ "installable": `False`,
+ "src": `"version/tz_version"`,
+ "dir": `"usr/share/tz"`,
+ })}})
+}
+
+func TestPrebuiltEtcNoSubdir(t *testing.T) {
+ runPrebuiltEtcTestCase(t, bp2buildTestCase{
+ description: "prebuilt_etc - no subdir",
+ filesystem: map[string]string{},
+ blueprint: `
+prebuilt_etc {
+ name: "apex_tz_version",
+ src: "version/tz_version",
+ filename: "tz_version",
+ installable: false,
+}
+`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("prebuilt_file", "apex_tz_version", attrNameToString{
+ "filename": `"tz_version"`,
+ "installable": `False`,
+ "src": `"version/tz_version"`,
+ "dir": `"etc"`,
})}})
}
diff --git a/build_test.bash b/build_test.bash
index 1dc6660..8b91e2c 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -25,7 +25,8 @@
# Products that are broken or otherwise don't work with multiproduct_kati
SKIPPED_PRODUCTS=(
- # Both of these products are for soong-only builds, and will fail the kati stage.
+ # These products are for soong-only builds, and will fail the kati stage.
+ linux_bionic
mainline_sdk
ndk
)
diff --git a/cc/Android.bp b/cc/Android.bp
index 9103a48..b105e7c 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -100,6 +100,7 @@
"proto_test.go",
"sanitize_test.go",
"test_data_test.go",
+ "tidy_test.go",
"vendor_public_library_test.go",
"vendor_snapshot_test.go",
],
diff --git a/cc/OWNERS b/cc/OWNERS
index a438b15..ffbf14a 100644
--- a/cc/OWNERS
+++ b/cc/OWNERS
@@ -1,4 +1,4 @@
per-file ndk_*.go = danalbert@google.com
-per-file tidy.go = srhines@google.com, chh@google.com
+per-file tidy*.go = srhines@google.com, chh@google.com
per-file afdo.go,afdo_test.go,lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
per-file coverage.go = pirama@google.com, srhines@google.com, allenhair@google.com
diff --git a/cc/bp2build.go b/cc/bp2build.go
index cc378b3..19855fa 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -167,21 +167,17 @@
attrs.System_dynamic_deps.ForceSpecifyEmptyList = true
if isStatic {
- for axis, configToProps := range module.GetArchVariantProperties(ctx, &StaticProperties{}) {
- for config, props := range configToProps {
- if staticOrSharedProps, ok := props.(*StaticProperties); ok {
- setAttrs(axis, config, staticOrSharedProps.Static)
- }
+ bp2BuildPropParseHelper(ctx, module, &StaticProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if staticOrSharedProps, ok := props.(*StaticProperties); ok {
+ setAttrs(axis, config, staticOrSharedProps.Static)
}
- }
+ })
} else {
- for axis, configToProps := range module.GetArchVariantProperties(ctx, &SharedProperties{}) {
- for config, props := range configToProps {
- if staticOrSharedProps, ok := props.(*SharedProperties); ok {
- setAttrs(axis, config, staticOrSharedProps.Shared)
- }
+ bp2BuildPropParseHelper(ctx, module, &SharedProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if staticOrSharedProps, ok := props.(*SharedProperties); ok {
+ setAttrs(axis, config, staticOrSharedProps.Shared)
}
- }
+ })
}
partitionedSrcs := groupSrcsByExtension(ctx, attrs.Srcs)
@@ -359,21 +355,18 @@
}
func (ca *compilerAttributes) convertStlProps(ctx android.ArchVariantContext, module *Module) {
- stlPropsByArch := module.GetArchVariantProperties(ctx, &StlProperties{})
- for _, configToProps := range stlPropsByArch {
- for _, props := range configToProps {
- if stlProps, ok := props.(*StlProperties); ok {
- if stlProps.Stl == nil {
- continue
- }
- if ca.stl == nil {
- ca.stl = stlProps.Stl
- } else if ca.stl != stlProps.Stl {
- ctx.ModuleErrorf("Unsupported conversion: module with different stl for different variants: %s and %s", *ca.stl, stlProps.Stl)
- }
+ bp2BuildPropParseHelper(ctx, module, &StlProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if stlProps, ok := props.(*StlProperties); ok {
+ if stlProps.Stl == nil {
+ return
+ }
+ if ca.stl == nil {
+ ca.stl = stlProps.Stl
+ } else if ca.stl != stlProps.Stl {
+ ctx.ModuleErrorf("Unsupported conversion: module with different stl for different variants: %s and %s", *ca.stl, stlProps.Stl)
}
}
- }
+ })
}
func (ca *compilerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) {
@@ -713,17 +706,15 @@
}
func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
- for axis, configToProps := range module.GetArchVariantProperties(ctx, &StripProperties{}) {
- for config, props := range configToProps {
- if stripProperties, ok := props.(*StripProperties); ok {
- la.stripKeepSymbols.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols)
- la.stripKeepSymbolsList.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_list)
- la.stripKeepSymbolsAndDebugFrame.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_and_debug_frame)
- la.stripAll.SetSelectValue(axis, config, stripProperties.Strip.All)
- la.stripNone.SetSelectValue(axis, config, stripProperties.Strip.None)
- }
+ bp2BuildPropParseHelper(ctx, module, &StripProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if stripProperties, ok := props.(*StripProperties); ok {
+ la.stripKeepSymbols.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols)
+ la.stripKeepSymbolsList.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_list)
+ la.stripKeepSymbolsAndDebugFrame.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_and_debug_frame)
+ la.stripAll.SetSelectValue(axis, config, stripProperties.Strip.All)
+ la.stripNone.SetSelectValue(axis, config, stripProperties.Strip.None)
}
- }
+ })
}
func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) {
@@ -859,18 +850,16 @@
} else {
exported = BazelIncludes{}
}
- for axis, configToProps := range module.GetArchVariantProperties(ctx, &FlagExporterProperties{}) {
- for config, props := range configToProps {
- if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
- if len(flagExporterProperties.Export_include_dirs) > 0 {
- exported.Includes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.Includes.SelectValue(axis, config), flagExporterProperties.Export_include_dirs...)))
- }
- if len(flagExporterProperties.Export_system_include_dirs) > 0 {
- exported.SystemIncludes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.SystemIncludes.SelectValue(axis, config), flagExporterProperties.Export_system_include_dirs...)))
- }
+ bp2BuildPropParseHelper(ctx, module, &FlagExporterProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
+ if len(flagExporterProperties.Export_include_dirs) > 0 {
+ exported.Includes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.Includes.SelectValue(axis, config), flagExporterProperties.Export_include_dirs...)))
+ }
+ if len(flagExporterProperties.Export_system_include_dirs) > 0 {
+ exported.SystemIncludes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.SystemIncludes.SelectValue(axis, config), flagExporterProperties.Export_system_include_dirs...)))
}
}
- }
+ })
exported.AbsoluteIncludes.DeduplicateAxesFromBase()
exported.Includes.DeduplicateAxesFromBase()
exported.SystemIncludes.DeduplicateAxesFromBase()
@@ -938,22 +927,19 @@
func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module) binaryLinkerAttrs {
attrs := binaryLinkerAttrs{}
- archVariantProps := m.GetArchVariantProperties(ctx, &BinaryLinkerProperties{})
- for axis, configToProps := range archVariantProps {
- for _, p := range configToProps {
- props := p.(*BinaryLinkerProperties)
- staticExecutable := props.Static_executable
- if axis == bazel.NoConfigAxis {
- if linkBinaryShared := !proptools.Bool(staticExecutable); !linkBinaryShared {
- attrs.Linkshared = &linkBinaryShared
- }
- } else if staticExecutable != nil {
- // TODO(b/202876379): Static_executable is arch-variant; however, linkshared is a
- // nonconfigurable attribute. Only 4 AOSP modules use this feature, defer handling
- ctx.ModuleErrorf("bp2build cannot migrate a module with arch/target-specific static_executable values")
+ bp2BuildPropParseHelper(ctx, m, &BinaryLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ linkerProps := props.(*BinaryLinkerProperties)
+ staticExecutable := linkerProps.Static_executable
+ if axis == bazel.NoConfigAxis {
+ if linkBinaryShared := !proptools.Bool(staticExecutable); !linkBinaryShared {
+ attrs.Linkshared = &linkBinaryShared
}
+ } else if staticExecutable != nil {
+ // TODO(b/202876379): Static_executable is arch-variant; however, linkshared is a
+ // nonconfigurable attribute. Only 4 AOSP modules use this feature, defer handling
+ ctx.ModuleErrorf("bp2build cannot migrate a module with arch/target-specific static_executable values")
}
- }
+ })
return attrs
}
diff --git a/cc/cc.go b/cc/cc.go
index 456b736..c2d0f6e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -746,6 +746,7 @@
runtimeDepTag = installDependencyTag{name: "runtime lib"}
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
stubImplDepTag = dependencyTag{name: "stub_impl"}
+ JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
)
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
diff --git a/cc/config/global.go b/cc/config/global.go
index 65bfbf0..3caf327 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -286,8 +286,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r450784c"
- ClangDefaultShortVersion = "14.0.5"
+ ClangDefaultVersion = "clang-r450784d"
+ ClangDefaultShortVersion = "14.0.6"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go
index 927fa2e..3456c32 100644
--- a/cc/ndk_abi.go
+++ b/cc/ndk_abi.go
@@ -46,7 +46,7 @@
if m, ok := module.(*Module); ok {
if installer, ok := m.installer.(*stubDecorator); ok {
- if canDumpAbi() {
+ if canDumpAbi(ctx.Config()) {
depPaths = append(depPaths, installer.abiDumpPath)
}
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index fc682ff..5ef41ea 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -53,9 +53,9 @@
abitidy = pctx.AndroidStaticRule("abitidy",
blueprint.RuleParams{
- Command: "$abitidy --all -i $in -o $out",
+ Command: "$abitidy --all $flags -i $in -o $out",
CommandDeps: []string{"$abitidy"},
- })
+ }, "flags")
abidiff = pctx.AndroidStaticRule("abidiff",
blueprint.RuleParams{
@@ -104,6 +104,12 @@
// used. This is only needed to work around platform bugs like
// https://github.com/android-ndk/ndk/issues/265.
Unversioned_until *string
+
+ // If true, does not emit errors when APIs lacking type information are
+ // found. This is false by default and should not be enabled outside bionic,
+ // where it is enabled pending a fix for http://b/190554910 (no debug info
+ // for asm implemented symbols).
+ Allow_untyped_symbols *bool
}
type stubDecorator struct {
@@ -315,8 +321,18 @@
}
// Feature flag.
-func canDumpAbi() bool {
- return runtime.GOOS != "darwin"
+func canDumpAbi(config android.Config) bool {
+ if runtime.GOOS == "darwin" {
+ return false
+ }
+ // abidw doesn't currently handle top-byte-ignore correctly. Disable ABI
+ // dumping for those configs while we wait for a fix. We'll still have ABI
+ // checking coverage from non-hwasan builds.
+ // http://b/190554910
+ if android.InList("hwaddress", config.SanitizeDevice()) {
+ return false
+ }
+ return true
}
// Feature flag to disable diffing against prebuilts.
@@ -339,14 +355,22 @@
"symbolList": symbolList.String(),
},
})
+
this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
this.apiLevel.String(), ctx.Arch().ArchType.String(),
this.libraryName(ctx), "abi.xml")
+ untypedFlag := "--abort-on-untyped-symbols"
+ if proptools.BoolDefault(this.properties.Allow_untyped_symbols, false) {
+ untypedFlag = ""
+ }
ctx.Build(pctx, android.BuildParams{
Rule: abitidy,
Description: fmt.Sprintf("abitidy %s", implementationLibrary),
Input: abiRawPath,
Output: this.abiDumpPath,
+ Args: map[string]string{
+ "flags": untypedFlag,
+ },
})
}
@@ -444,7 +468,7 @@
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile, c.apiLevel, "")
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
c.versionScriptPath = nativeAbiResult.versionScript
- if canDumpAbi() {
+ if canDumpAbi(ctx.Config()) {
c.dumpAbi(ctx, nativeAbiResult.symbolList)
if canDiffAbi() {
c.diffAbi(ctx)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 4ad8a90..f54c6f8 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -527,7 +527,16 @@
func (p *prebuiltObjectLinker) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
if len(p.properties.Srcs) > 0 {
- return p.Prebuilt.SingleSourcePath(ctx)
+ // Copy objects to a name matching the final installed name
+ in := p.Prebuilt.SingleSourcePath(ctx)
+ outputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".o")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpExecutable,
+ Description: "prebuilt",
+ Output: outputFile,
+ Input: in,
+ })
+ return outputFile
}
return nil
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 814fef6..53169de 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -969,6 +969,22 @@
})
}
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
+ // If it's a Java module with native dependencies through jni,
+ // set the sanitizer for them
+ if jniSanitizeable, ok := mctx.Module().(JniSanitizeable); ok {
+ if jniSanitizeable.IsSanitizerEnabledForJni(mctx, t.name()) {
+ mctx.VisitDirectDeps(func(child android.Module) {
+ if c, ok := child.(PlatformSanitizeable); ok &&
+ mctx.OtherModuleDependencyTag(child) == JniFuzzLibTag &&
+ c.SanitizePropDefined() &&
+ !c.SanitizeNever() &&
+ !c.IsSanitizerExplicitlyDisabled(t) {
+ c.SetSanitizeDep(true)
+ }
+ })
+ }
+ }
+
// If an APEX module includes a lib which is enabled for a sanitizer T, then
// the APEX module is also enabled for the same sanitizer type.
mctx.VisitDirectDeps(func(child android.Module) {
@@ -1280,6 +1296,11 @@
AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string)
}
+type JniSanitizeable interface {
+ android.Module
+ IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool
+}
+
func (c *Module) MinimalRuntimeDep() bool {
return c.sanitize.Properties.MinimalRuntimeDep
}
@@ -1407,7 +1428,7 @@
}
c.SetSanitizeDep(false)
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
- // APEX modules fall here
+ // APEX and Java fuzz modules fall here
sanitizeable.AddSanitizerDependencies(mctx, t.name())
mctx.CreateVariations(t.variationName())
} else if c, ok := mctx.Module().(*Module); ok {
diff --git a/cc/tidy.go b/cc/tidy.go
index 750e9de..03e967d 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -76,9 +76,10 @@
// the global WITH_TIDY or module 'tidy' property is true.
flags.Tidy = true
- // If explicitly enabled, by global default or local tidy property,
+ // If explicitly enabled, by global WITH_TIDY or local tidy:true property,
// set flags.NeedTidyFiles to make this module depend on .tidy files.
- if ctx.Config().ClangTidy() || Bool(tidy.Properties.Tidy) {
+ // Note that locally set tidy:true is ignored if ALLOW_LOCAL_TIDY_TRUE is not set to true.
+ if ctx.Config().IsEnvTrue("WITH_TIDY") || (ctx.Config().IsEnvTrue("ALLOW_LOCAL_TIDY_TRUE") && Bool(tidy.Properties.Tidy)) {
flags.NeedTidyFiles = true
}
diff --git a/cc/tidy_test.go b/cc/tidy_test.go
new file mode 100644
index 0000000..339b302
--- /dev/null
+++ b/cc/tidy_test.go
@@ -0,0 +1,98 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestWithTidy(t *testing.T) {
+ // When WITH_TIDY=1 or (ALLOW_LOCAL_TIDY_TRUE=1 and local tidy:true)
+ // a C++ library should depend on .tidy files.
+ testCases := []struct {
+ withTidy, allowLocalTidyTrue string // "_" means undefined
+ needTidyFile []bool // for {libfoo_0, libfoo_1} and {libbar_0, libbar_1}
+ }{
+ {"_", "_", []bool{false, false, false}},
+ {"_", "0", []bool{false, false, false}},
+ {"_", "1", []bool{false, true, false}},
+ {"_", "true", []bool{false, true, false}},
+ {"0", "_", []bool{false, false, false}},
+ {"0", "1", []bool{false, true, false}},
+ {"1", "_", []bool{true, true, false}},
+ {"1", "false", []bool{true, true, false}},
+ {"1", "1", []bool{true, true, false}},
+ {"true", "_", []bool{true, true, false}},
+ }
+ bp := `
+ cc_library_shared {
+ name: "libfoo_0", // depends on .tidy if WITH_TIDY=1
+ srcs: ["foo.c"],
+ }
+ cc_library_shared { // depends on .tidy if WITH_TIDY=1 or ALLOW_LOCAL_TIDY_TRUE=1
+ name: "libfoo_1",
+ srcs: ["foo.c"],
+ tidy: true,
+ }
+ cc_library_shared { // no .tidy
+ name: "libfoo_2",
+ srcs: ["foo.c"],
+ tidy: false,
+ }
+ cc_library_static {
+ name: "libbar_0", // depends on .tidy if WITH_TIDY=1
+ srcs: ["bar.c"],
+ }
+ cc_library_static { // depends on .tidy if WITH_TIDY=1 or ALLOW_LOCAL_TIDY_TRUE=1
+ name: "libbar_1",
+ srcs: ["bar.c"],
+ tidy: true,
+ }
+ cc_library_static { // no .tidy
+ name: "libbar_2",
+ srcs: ["bar.c"],
+ tidy: false,
+ }`
+ for index, test := range testCases {
+ testName := fmt.Sprintf("case%d,%v,%v", index, test.withTidy, test.allowLocalTidyTrue)
+ t.Run(testName, func(t *testing.T) {
+ testEnv := map[string]string{}
+ if test.withTidy != "_" {
+ testEnv["WITH_TIDY"] = test.withTidy
+ }
+ if test.allowLocalTidyTrue != "_" {
+ testEnv["ALLOW_LOCAL_TIDY_TRUE"] = test.allowLocalTidyTrue
+ }
+ ctx := android.GroupFixturePreparers(prepareForCcTest, android.FixtureMergeEnv(testEnv)).RunTestWithBp(t, bp)
+ for n := 0; n < 3; n++ {
+ checkLibraryRule := func(foo, variant, ruleName string) {
+ libName := fmt.Sprintf("lib%s_%d", foo, n)
+ tidyFile := "out/soong/.intermediates/" + libName + "/" + variant + "/obj/" + foo + ".tidy"
+ depFiles := ctx.ModuleForTests(libName, variant).Rule(ruleName).Validations.Strings()
+ if test.needTidyFile[n] {
+ android.AssertStringListContains(t, libName+" needs .tidy file", depFiles, tidyFile)
+ } else {
+ android.AssertStringListDoesNotContain(t, libName+" does not need .tidy file", depFiles, tidyFile)
+ }
+ }
+ checkLibraryRule("foo", "android_arm64_armv8-a_shared", "ld")
+ checkLibraryRule("bar", "android_arm64_armv8-a_static", "ar")
+ }
+ })
+ }
+}
diff --git a/cc/util.go b/cc/util.go
index b256b9a..4e10037 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -15,9 +15,7 @@
package cc
import (
- "fmt"
"path/filepath"
- "regexp"
"strings"
"android/soong/android"
@@ -30,30 +28,12 @@
return android.JoinWithPrefix(dirs.Strings(), "-I")
}
-func ldDirsToFlags(dirs []string) string {
- return android.JoinWithPrefix(dirs, "-L")
-}
-
-func libNamesToFlags(names []string) string {
- return android.JoinWithPrefix(names, "-l")
-}
-
var indexList = android.IndexList
var inList = android.InList
var filterList = android.FilterList
var removeListFromList = android.RemoveListFromList
var removeFromList = android.RemoveFromList
-var libNameRegexp = regexp.MustCompile(`^lib(.*)$`)
-
-func moduleToLibName(module string) (string, error) {
- matches := libNameRegexp.FindStringSubmatch(module)
- if matches == nil {
- return "", fmt.Errorf("Library module name %s does not start with lib", module)
- }
- return matches[1], nil
-}
-
func flagsToBuilderFlags(in Flags) builderFlags {
return builderFlags{
globalCommonFlags: strings.Join(in.Global.CommonFlags, " "),
@@ -113,13 +93,6 @@
return list
}
-func addSuffix(list []string, suffix string) []string {
- for i := range list {
- list[i] = list[i] + suffix
- }
- return list
-}
-
// linkDirOnDevice/linkName -> target
func makeSymlinkCmd(linkDirOnDevice string, linkName string, target string) string {
dir := filepath.Join("$(PRODUCT_OUT)", linkDirOnDevice)
diff --git a/cmd/go2bp/go2bp.go b/cmd/go2bp/go2bp.go
index 07cb5df..fb5a746 100644
--- a/cmd/go2bp/go2bp.go
+++ b/cmd/go2bp/go2bp.go
@@ -335,12 +335,15 @@
}
cmd := exec.Command("go", "list", "-json", "./...")
- output, err := cmd.Output()
- if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to dump the go packages: %v\n", err)
+ var stdoutb, stderrb bytes.Buffer
+ cmd.Stdout = &stdoutb
+ cmd.Stderr = &stderrb
+ if err := cmd.Run(); err != nil {
+ fmt.Fprintf(os.Stderr, "Running %q to dump the Go packages failed: %v, stderr:\n%s\n",
+ cmd.String(), err, stderrb.Bytes())
os.Exit(1)
}
- decoder := json.NewDecoder(bytes.NewReader(output))
+ decoder := json.NewDecoder(bytes.NewReader(stdoutb.Bytes()))
pkgs := []*GoPackage{}
pkgMap := map[string]*GoPackage{}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index a142833..719771f 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -474,6 +474,7 @@
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
android.InitDefaultableModule(module)
+ android.InitBazelModule(module)
return module
}
@@ -668,25 +669,17 @@
// For Bazel / bp2build
-type bazelPrebuiltEtcAttributes struct {
+type bazelPrebuiltFileAttributes struct {
Src bazel.LabelAttribute
Filename string
- Sub_dir string
+ Dir string
Installable bazel.BoolAttribute
}
// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
-func (p *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- // All prebuilt_* modules are PrebuiltEtc, but at this time, we only convert prebuilt_etc modules.
- if p.installDirBase != "etc" {
- return
- }
-
- prebuiltEtcBp2BuildInternal(ctx, p)
-}
-
-func prebuiltEtcBp2BuildInternal(ctx android.TopDownMutatorContext, module *PrebuiltEtc) {
- var srcLabelAttribute bazel.LabelAttribute
+// All prebuilt_* modules are PrebuiltEtc, which we treat uniformily as *PrebuiltFile*
+func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ var src bazel.LabelAttribute
for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) {
for config, p := range configToProps {
props, ok := p.(*prebuiltEtcProperties)
@@ -695,7 +688,7 @@
}
if props.Src != nil {
label := android.BazelLabelForModuleSrcSingle(ctx, *props.Src)
- srcLabelAttribute.SetSelectValue(axis, config, label)
+ src.SetSelectValue(axis, config, label)
}
}
}
@@ -705,26 +698,30 @@
filename = *module.properties.Filename
}
- var subDir string
- if module.subdirProperties.Sub_dir != nil {
- subDir = *module.subdirProperties.Sub_dir
+ var dir = module.installDirBase
+ // prebuilt_file supports only `etc` or `usr/share`
+ if !(dir == "etc" || dir == "usr/share") {
+ return
+ }
+ if subDir := module.subdirProperties.Sub_dir; subDir != nil {
+ dir = dir + "/" + *subDir
}
- var installableBoolAttribute bazel.BoolAttribute
- if module.properties.Installable != nil {
- installableBoolAttribute.Value = module.properties.Installable
+ var installable bazel.BoolAttribute
+ if install := module.properties.Installable; install != nil {
+ installable.Value = install
}
- attrs := &bazelPrebuiltEtcAttributes{
- Src: srcLabelAttribute,
+ attrs := &bazelPrebuiltFileAttributes{
+ Src: src,
Filename: filename,
- Sub_dir: subDir,
- Installable: installableBoolAttribute,
+ Dir: dir,
+ Installable: installable,
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "prebuilt_etc",
- Bzl_load_location: "//build/bazel/rules:prebuilt_etc.bzl",
+ Rule_class: "prebuilt_file",
+ Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl",
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 33beb37..352b451 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -228,6 +228,15 @@
return output
}
+// Calculates avb_salt from some input for deterministic output.
+func (b *bootimg) salt() string {
+ var input []string
+ input = append(input, b.properties.Cmdline...)
+ input = append(input, proptools.StringDefault(b.properties.Partition_name, b.Name()))
+ input = append(input, proptools.String(b.properties.Header_version))
+ return sha1sum(input)
+}
+
func (b *bootimg) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
var sb strings.Builder
var deps android.Paths
@@ -248,6 +257,7 @@
addStr("avb_add_hash_footer_args", "") // TODO(jiyong): add --rollback_index
partitionName := proptools.StringDefault(b.properties.Partition_name, b.Name())
addStr("partition_name", partitionName)
+ addStr("avb_salt", b.salt())
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
android.WriteFileRule(ctx, propFile, sb.String())
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index ccf9e9d..6e1e78a 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -15,7 +15,9 @@
package filesystem
import (
+ "crypto/sha256"
"fmt"
+ "io"
"path/filepath"
"strings"
@@ -88,6 +90,13 @@
// Symbolic links to be created under root with "ln -sf <target> <name>".
Symlinks []symlinkDefinition
+
+ // Seconds since unix epoch to override timestamps of file entries
+ Fake_timestamp *string
+
+ // When set, passed to mkuserimg_mke2fs --mke2fs_uuid & --mke2fs_hash_seed.
+ // Otherwise, they'll be set as random which might cause indeterministic build output.
+ Uuid *string
}
// android_filesystem packages a set of modules and their transitive dependencies into a filesystem
@@ -276,6 +285,11 @@
return fcBin.OutputPath
}
+// Calculates avb_salt from entry list (sorted) for deterministic output.
+func (f *filesystem) salt() string {
+ return sha1sum(f.entries)
+}
+
func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
type prop struct {
name string
@@ -321,12 +335,19 @@
addStr("avb_add_hashtree_footer_args", "--do_not_generate_fec")
partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name())
addStr("partition_name", partitionName)
+ addStr("avb_salt", f.salt())
}
if proptools.String(f.properties.File_contexts) != "" {
addPath("selinux_fc", f.buildFileContexts(ctx))
}
-
+ if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" {
+ addStr("timestamp", timestamp)
+ }
+ if uuid := proptools.String(f.properties.Uuid); uuid != "" {
+ addStr("uuid", uuid)
+ addStr("hash_seed", uuid)
+ }
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Text("rm").Flag("-rf").Output(propFile)
@@ -451,3 +472,11 @@
}
return specs
}
+
+func sha1sum(values []string) string {
+ h := sha256.New()
+ for _, value := range values {
+ io.WriteString(h, value)
+ }
+ return fmt.Sprintf("%x", h.Sum(nil))
+}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 89f8187..700cdf0 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -82,6 +82,9 @@
Hwasan_options []string `json:"hwasan_options,omitempty"`
// Additional options to be passed to HWASAN when running on host in Haiku.
Asan_options []string `json:"asan_options,omitempty"`
+ // If there's a Java fuzzer with JNI, a different version of Jazzer would
+ // need to be added to the fuzzer package than one without JNI
+ IsJni *bool `json:"is_jni,omitempty"`
}
type FuzzProperties struct {
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 7772b70..3fa3520 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -82,8 +82,8 @@
if minSdkVersion.FinalOrFutureInt() >= 23 {
args = append(args, fmt.Sprintf("--extract-native-libs=%v", !params.UseEmbeddedNativeLibs))
} else if params.UseEmbeddedNativeLibs {
- ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
- minSdkVersion)
+ ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%s doesn't support it",
+ minSdkVersion.String())
}
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 80b828d..f6ea6a9 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -132,6 +132,16 @@
return entriesList
}
+func (j *JavaFuzzLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+ entriesList := j.Library.AndroidMkEntries()
+ entries := &entriesList[0]
+ entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", "null-suite")
+ androidMkWriteTestData(j.jniFilePaths, entries)
+ })
+ return entriesList
+}
+
// Called for modules that are a component of a test suite.
func testSuiteComponent(entries *android.AndroidMkEntries, test_suites []string, perTestcaseDirectory bool) {
entries.SetString("LOCAL_MODULE_TAGS", "tests")
diff --git a/java/base.go b/java/base.go
index b925350..4932c48 100644
--- a/java/base.go
+++ b/java/base.go
@@ -442,9 +442,6 @@
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
- // map of SDK version to class loader context
- classLoaderContexts dexpreopt.ClassLoaderContextMap
-
// list of plugins that this java module is exporting
exportedPluginJars android.Paths
@@ -1481,11 +1478,30 @@
}
if ctx.Device() {
- lintSDKVersionString := func(sdkSpec android.SdkSpec) string {
+ lintSDKVersion := func(sdkSpec android.SdkSpec) int {
if v := sdkSpec.ApiLevel; !v.IsPreview() {
- return v.String()
+ return v.FinalInt()
} else {
- return ctx.Config().DefaultAppTargetSdk(ctx).String()
+ // When running metalava, we pass --version-codename. When that value
+ // is not REL, metalava will add 1 to the --current-version argument.
+ // On old branches, PLATFORM_SDK_VERSION is the latest version (for that
+ // branch) and the codename is REL, except potentially on the most
+ // recent non-master branch. On that branch, it goes through two other
+ // phases before it gets to the phase previously described:
+ // - PLATFORM_SDK_VERSION has not been updated yet, and the codename
+ // is not rel. This happens for most of the internal branch's life
+ // while the branch has been cut but is still under active development.
+ // - PLATFORM_SDK_VERSION has been set, but the codename is still not
+ // REL. This happens briefly during the release process. During this
+ // state the code to add --current-version is commented out, and then
+ // that commenting out is reverted after the codename is set to REL.
+ // On the master branch, the PLATFORM_SDK_VERSION always represents a
+ // prior version and the codename is always non-REL.
+ //
+ // We need to add one here to match metalava adding 1. Technically
+ // this means that in the state described in the second bullet point
+ // above, this number is 1 higher than it should be.
+ return ctx.Config().PlatformSdkVersion().FinalInt() + 1
}
}
@@ -1494,9 +1510,9 @@
j.linter.srcJars = srcJars
j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...)
j.linter.classes = j.implementationJarFile
- j.linter.minSdkVersion = lintSDKVersionString(j.MinSdkVersion(ctx))
- j.linter.targetSdkVersion = lintSDKVersionString(j.TargetSdkVersion(ctx))
- j.linter.compileSdkVersion = lintSDKVersionString(j.SdkVersion(ctx))
+ j.linter.minSdkVersion = lintSDKVersion(j.MinSdkVersion(ctx))
+ j.linter.targetSdkVersion = lintSDKVersion(j.TargetSdkVersion(ctx))
+ j.linter.compileSdkVersion = lintSDKVersion(j.SdkVersion(ctx))
j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
diff --git a/java/config/config.go b/java/config/config.go
index 95b841f..46c91a2 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -81,7 +81,17 @@
exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "4096M")
exportedVars.ExportStringStaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
- exportedVars.ExportStringListStaticVariable("DexFlags", []string{
+ // D8 invocations are shorter lived, so we restrict their JIT tiering relative to R8.
+ // Note that the `-JXX` prefix syntax is specific to the R8/D8 invocation wrappers.
+ exportedVars.ExportStringListStaticVariable("D8Flags", []string{
+ `-JXX:OnError="cat hs_err_pid%p.log"`,
+ "-JXX:CICompilerCount=6",
+ "-JXX:+UseDynamicNumberOfGCThreads",
+ "-JXX:+TieredCompilation",
+ "-JXX:TieredStopAtLevel=1",
+ })
+
+ exportedVars.ExportStringListStaticVariable("R8Flags", []string{
`-JXX:OnError="cat hs_err_pid%p.log"`,
"-JXX:CICompilerCount=6",
"-JXX:+UseDynamicNumberOfGCThreads",
diff --git a/java/config/makevars.go b/java/config/makevars.go
index df447a1..bc6848f 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -78,7 +78,8 @@
ctx.Strict("CLASS2NONSDKLIST", "${Class2NonSdkList}")
ctx.Strict("HIDDENAPI", "${HiddenAPI}")
- ctx.Strict("DEX_FLAGS", "${DexFlags}")
+ ctx.Strict("D8_FLAGS", "${D8Flags}")
+ ctx.Strict("R8_FLAGS", "${R8Flags}")
ctx.Strict("AIDL", "${AidlCmd}")
ctx.Strict("AAPT2", "${Aapt2Cmd}")
diff --git a/java/dex.go b/java/dex.go
index 84665e7..13d6e4a 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -95,7 +95,7 @@
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`mkdir -p $$(dirname $tmpJar) && ` +
`${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
- `$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $tmpJar && ` +
+ `$d8Template${config.D8Cmd} ${config.D8Flags} --output $outDir $d8Flags $tmpJar && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
@@ -128,7 +128,7 @@
`mkdir -p $$(dirname ${outUsage}) && ` +
`mkdir -p $$(dirname $tmpJar) && ` +
`${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
- `$r8Template${config.R8Cmd} ${config.DexFlags} -injars $tmpJar --output $outDir ` +
+ `$r8Template${config.R8Cmd} ${config.R8Flags} -injars $tmpJar --output $outDir ` +
`--no-data-resources ` +
`-printmapping ${outDict} ` +
`-printusage ${outUsage} ` +
diff --git a/java/fuzz.go b/java/fuzz.go
index 257f343..584c80b 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -15,14 +15,25 @@
package java
import (
- "github.com/google/blueprint/proptools"
"sort"
"strings"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
+ "android/soong/cc"
"android/soong/fuzz"
)
+type jniProperties struct {
+ // list of jni libs
+ Jni_libs []string
+
+ // sanitization
+ Sanitizers []string
+}
+
func init() {
RegisterJavaFuzzBuildComponents(android.InitRegistrationContext)
}
@@ -35,11 +46,60 @@
type JavaFuzzLibrary struct {
Library
fuzzPackagedModule fuzz.FuzzPackagedModule
+ jniProperties jniProperties
+ jniFilePaths android.Paths
+}
+
+// IsSanitizerEnabled implemented to make JavaFuzzLibrary implement
+// cc.Sanitizeable
+func (j *JavaFuzzLibrary) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool {
+ for _, s := range j.jniProperties.Sanitizers {
+ if sanitizerName == s {
+ return true
+ }
+ }
+ return false
+}
+
+// IsSanitizerEnabledForJni implemented to make JavaFuzzLibrary implement
+// cc.JniSanitizeable. It returns a bool for whether a cc dependency should be
+// sanitized for the given sanitizer or not.
+func (j *JavaFuzzLibrary) IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool {
+ return j.IsSanitizerEnabled(ctx, sanitizerName)
+}
+
+// EnableSanitizer implemented to make JavaFuzzLibrary implement
+// cc.Sanitizeable
+func (j *JavaFuzzLibrary) EnableSanitizer(sanitizerName string) {
+}
+
+// AddSanitizerDependencies implemented to make JavaFuzzLibrary implement
+// cc.Sanitizeable
+func (j *JavaFuzzLibrary) AddSanitizerDependencies(mctx android.BottomUpMutatorContext, sanitizerName string) {
+}
+
+// To verify that JavaFuzzLibrary implements cc.Sanitizeable
+var _ cc.Sanitizeable = (*JavaFuzzLibrary)(nil)
+
+func (j *JavaFuzzLibrary) DepsMutator(mctx android.BottomUpMutatorContext) {
+ if len(j.jniProperties.Jni_libs) > 0 {
+ if j.fuzzPackagedModule.FuzzProperties.Fuzz_config == nil {
+ config := &fuzz.FuzzConfig{}
+ j.fuzzPackagedModule.FuzzProperties.Fuzz_config = config
+ }
+ // this will be used by the ingestion pipeline to determine the version
+ // of jazzer to add to the fuzzer package
+ j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
+
+ for _, target := range mctx.MultiTargets() {
+ sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
+ mctx.AddFarVariationDependencies(sharedLibVariations, cc.JniFuzzLibTag, j.jniProperties.Jni_libs...)
+ }
+ }
+ j.Library.DepsMutator(mctx)
}
func (j *JavaFuzzLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- j.Library.GenerateAndroidBuildActions(ctx)
-
if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
}
@@ -55,6 +115,23 @@
android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
j.fuzzPackagedModule.Config = configPath
}
+
+ ctx.VisitDirectDepsWithTag(cc.JniFuzzLibTag, func(dep android.Module) {
+ sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
+ if sharedLibInfo.SharedLibrary != nil {
+ libPath := android.PathForModuleOut(ctx, sharedLibInfo.SharedLibrary.Base())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: sharedLibInfo.SharedLibrary,
+ Output: libPath,
+ })
+ j.jniFilePaths = append(j.jniFilePaths, libPath)
+ } else {
+ ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
+ }
+ })
+
+ j.Library.GenerateAndroidBuildActions(ctx)
}
// java_fuzz builds and links sources into a `.jar` file for the host.
@@ -65,7 +142,8 @@
module := &JavaFuzzLibrary{}
module.addHostProperties()
- module.Module.properties.Installable = proptools.BoolPtr(false)
+ module.AddProperties(&module.jniProperties)
+ module.Module.properties.Installable = proptools.BoolPtr(true)
module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
// java_fuzz packaging rules collide when both linux_glibc and linux_bionic are enabled, disable the linux_bionic variants.
@@ -83,7 +161,7 @@
module.initModuleAndImport(module)
android.InitSdkAwareModule(module)
- InitJavaModule(module, android.HostSupported)
+ InitJavaModuleMultiTargets(module, android.HostSupported)
return module
}
@@ -106,26 +184,26 @@
ctx.VisitAllModules(func(module android.Module) {
// Discard non-fuzz targets.
- javaModule, ok := module.(*JavaFuzzLibrary)
+ javaFuzzModule, ok := module.(*JavaFuzzLibrary)
if !ok {
return
}
fuzzModuleValidator := fuzz.FuzzModule{
- javaModule.ModuleBase,
- javaModule.DefaultableModuleBase,
- javaModule.ApexModuleBase,
+ javaFuzzModule.ModuleBase,
+ javaFuzzModule.DefaultableModuleBase,
+ javaFuzzModule.ApexModuleBase,
}
- if ok := fuzz.IsValid(fuzzModuleValidator); !ok || *javaModule.Module.properties.Installable {
+ if ok := fuzz.IsValid(fuzzModuleValidator); !ok {
return
}
hostOrTargetString := "target"
- if javaModule.Host() {
+ if javaFuzzModule.Host() {
hostOrTargetString = "host"
}
- archString := javaModule.Arch().ArchType.String()
+ archString := javaFuzzModule.Arch().ArchType.String()
archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
@@ -134,12 +212,17 @@
builder := android.NewRuleBuilder(pctx, ctx)
// Package the artifacts (data, corpus, config and dictionary into a zipfile.
- files = s.PackageArtifacts(ctx, module, javaModule.fuzzPackagedModule, archDir, builder)
+ files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
// Add .jar
- files = append(files, fuzz.FileToZip{javaModule.outputFile, ""})
+ files = append(files, fuzz.FileToZip{javaFuzzModule.outputFile, ""})
- archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaModule.fuzzPackagedModule, files, builder, archDir, archString, "host", archOs, archDirs)
+ // Add jni .so files
+ for _, fPath := range javaFuzzModule.jniFilePaths {
+ files = append(files, fuzz.FileToZip{fPath, ""})
+ }
+
+ archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
if !ok {
return
}
diff --git a/java/fuzz_test.go b/java/fuzz_test.go
index cf063eb..0a2c945 100644
--- a/java/fuzz_test.go
+++ b/java/fuzz_test.go
@@ -15,13 +15,17 @@
package java
import (
- "android/soong/android"
"path/filepath"
+ "runtime"
"testing"
+
+ "android/soong/android"
+ "android/soong/cc"
)
var prepForJavaFuzzTest = android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
+ cc.PrepareForTestWithCcBuildComponents,
android.FixtureRegisterWithContext(RegisterJavaFuzzBuildComponents),
)
@@ -32,6 +36,13 @@
srcs: ["a.java"],
libs: ["bar"],
static_libs: ["baz"],
+ jni_libs: [
+ "libjni",
+ ],
+ sanitizers: [
+ "address",
+ "fuzzer",
+ ],
}
java_library_host {
@@ -42,11 +53,21 @@
java_library_host {
name: "baz",
srcs: ["c.java"],
- }`)
+ }
+
+ cc_library_shared {
+ name: "libjni",
+ host_supported: true,
+ device_supported: false,
+ stl: "none",
+ }
+ `)
osCommonTarget := result.Config.BuildOSCommonTarget.String()
- javac := result.ModuleForTests("foo", osCommonTarget).Rule("javac")
- combineJar := result.ModuleForTests("foo", osCommonTarget).Description("for javac")
+
+ osCommonTargetWithSan := osCommonTarget + "_asan" + "_fuzzer"
+ javac := result.ModuleForTests("foo", osCommonTargetWithSan).Rule("javac")
+ combineJar := result.ModuleForTests("foo", osCommonTargetWithSan).Description("for javac")
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
@@ -62,4 +83,18 @@
if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
}
+
+ ctx := result.TestContext
+ foo := ctx.ModuleForTests("foo", osCommonTargetWithSan).Module().(*JavaFuzzLibrary)
+
+ expected := "libjni.so"
+ if runtime.GOOS == "darwin" {
+ expected = "libjni.dylib"
+ }
+
+ fooJniFilePaths := foo.jniFilePaths
+ if len(fooJniFilePaths) != 1 || fooJniFilePaths[0].Rel() != expected {
+ t.Errorf(`expected foo test data relative path [%q], got %q`,
+ expected, fooJniFilePaths.Strings())
+ }
}
diff --git a/java/lint.go b/java/lint.go
index e97c9c2..f09db95 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -17,6 +17,7 @@
import (
"fmt"
"sort"
+ "strconv"
"strings"
"github.com/google/blueprint/proptools"
@@ -75,9 +76,9 @@
extraLintCheckJars android.Paths
test bool
library bool
- minSdkVersion string
- targetSdkVersion string
- compileSdkVersion string
+ minSdkVersion int
+ targetSdkVersion int
+ compileSdkVersion int
compileSdkKind android.SdkKind
javaLanguageLevel string
kotlinLanguageLevel string
@@ -299,7 +300,7 @@
Text(`echo "<?xml version='1.0' encoding='utf-8'?>" &&`).
Text(`echo "<manifest xmlns:android='http://schemas.android.com/apk/res/android'" &&`).
Text(`echo " android:versionCode='1' android:versionName='1' >" &&`).
- Textf(`echo " <uses-sdk android:minSdkVersion='%s' android:targetSdkVersion='%s'/>" &&`,
+ Textf(`echo " <uses-sdk android:minSdkVersion='%d' android:targetSdkVersion='%d'/>" &&`,
l.minSdkVersion, l.targetSdkVersion).
Text(`echo "</manifest>"`).
Text(") >").Output(manifestPath)
@@ -427,7 +428,7 @@
FlagWithOutput("--html ", html).
FlagWithOutput("--text ", text).
FlagWithOutput("--xml ", xml).
- FlagWithArg("--compile-sdk-version ", l.compileSdkVersion).
+ FlagWithArg("--compile-sdk-version ", strconv.Itoa(l.compileSdkVersion)).
FlagWithArg("--java-language-level ", l.javaLanguageLevel).
FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 4bc0c5f..1eee354 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -28,6 +28,11 @@
--disable_check SuspiciousImport
--disable_check UnusedResources
--disable_check ViewConstructor
+# Disable NewApi checks for the platform since platform is the one that implements
+# the API. This prevents noisy lint warnings like b/228956345#1
+# NewApi checks will continue to be enforced for apex deps since
+# lint.strict_updatability_linting will be true for those Soong modules
+--disable_check NewApi
# Downgrade existing errors to warnings
--warning_check AppCompatResource # 55 occurences in 10 modules
@@ -66,7 +71,6 @@
--warning_check MissingTvBanner # 3 occurences in 3 modules
--warning_check NamespaceTypo # 3 occurences in 3 modules
--warning_check NetworkSecurityConfig # 46 occurences in 12 modules
---warning_check NewApi # 1996 occurences in 122 modules
--warning_check NotSibling # 15 occurences in 10 modules
--warning_check ObjectAnimatorBinding # 14 occurences in 5 modules
--warning_check OnClick # 49 occurences in 21 modules
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 8f4fea4..02b3d08 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -531,7 +531,7 @@
func (ctx *parseContext) handleAssignment(a *mkparser.Assignment) []starlarkNode {
// Handle only simple variables
- if !a.Name.Const() {
+ if !a.Name.Const() || a.Target != nil {
return []starlarkNode{ctx.newBadNode(a, "Only simple variables are handled")}
}
name := a.Name.Strings[0]
@@ -542,6 +542,12 @@
if strings.HasPrefix(name, "override ") {
return []starlarkNode{ctx.newBadNode(a, "cannot handle override directive")}
}
+ if name == ".KATI_READONLY" {
+ // Skip assignments to .KATI_READONLY. If it was in the output file, it
+ // would be an error because it would be sorted before the definition of
+ // the variable it's trying to make readonly.
+ return []starlarkNode{}
+ }
// Soong configuration
if strings.HasPrefix(name, soongNsPrefix) {
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index de75129..9485a42 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -1242,13 +1242,15 @@
desc: "Ignore make rules",
mkname: "product.mk",
in: `
+foo: PRIVATE_VARIABLE = some_tool $< $@
foo: foo.c
gcc -o $@ $*`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.mk2rbc_error("product.mk:2", "unsupported line rule: foo: foo.c\n#gcc -o $@ $*")
+ rblf.mk2rbc_error("product.mk:2", "Only simple variables are handled")
+ rblf.mk2rbc_error("product.mk:3", "unsupported line rule: foo: foo.c\n#gcc -o $@ $*")
`,
},
{
@@ -1529,6 +1531,20 @@
cfg["PRODUCT_COPY_FILES"] += ("%s:foo/bar/%s" % (g.get("MY_OTHER_VAR", ""), x)).split()
`,
},
+ {
+ desc: ".KATI_READONLY",
+ mkname: "product.mk",
+ in: `
+MY_VAR := foo
+.KATI_READONLY := MY_VAR
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ g["MY_VAR"] = "foo"
+`,
+ },
}
var known_variables = []struct {
diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go
index ae96e1f..e49f3d4 100644
--- a/provenance/provenance_singleton.go
+++ b/provenance/provenance_singleton.go
@@ -60,29 +60,32 @@
}
type provenanceInfoSingleton struct {
+ mergedMetaDataFile android.OutputPath
}
-func (b *provenanceInfoSingleton) GenerateBuildActions(context android.SingletonContext) {
+func (p *provenanceInfoSingleton) GenerateBuildActions(context android.SingletonContext) {
allMetaDataFiles := make([]android.Path, 0)
context.VisitAllModulesIf(moduleFilter, func(module android.Module) {
if p, ok := module.(ProvenanceMetadata); ok {
allMetaDataFiles = append(allMetaDataFiles, p.ProvenanceMetaDataFile())
}
})
- mergedMetaDataFile := android.PathForOutput(context, "provenance_metadata.textproto")
+ p.mergedMetaDataFile = android.PathForOutput(context, "provenance_metadata.textproto")
context.Build(pctx, android.BuildParams{
Rule: mergeProvenanceMetaData,
Description: "merge provenance metadata",
Inputs: allMetaDataFiles,
- Output: mergedMetaDataFile,
+ Output: p.mergedMetaDataFile,
})
context.Build(pctx, android.BuildParams{
Rule: blueprint.Phony,
Description: "phony rule of merge provenance metadata",
- Inputs: []android.Path{mergedMetaDataFile},
+ Inputs: []android.Path{p.mergedMetaDataFile},
Output: android.PathForPhony(context, "provenance_metadata"),
})
+
+ context.Phony("droidcore", android.PathForPhony(context, "provenance_metadata"))
}
func moduleFilter(module android.Module) bool {
@@ -110,3 +113,9 @@
return artifactMetaDataFile
}
+
+func (p *provenanceInfoSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoal("droidcore", p.mergedMetaDataFile)
+}
+
+var _ android.SingletonMakeVarsProvider = (*provenanceInfoSingleton)(nil)
diff --git a/rust/config/global.go b/rust/config/global.go
index 2d5fa99..6bfa9cf 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.59.0"
+ RustDefaultVersion = "1.60.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 4c847a1..4773579 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -188,3 +188,8 @@
"get_clang_version.py",
],
}
+
+sh_binary_host {
+ name: "list_image",
+ src: "list_image.sh",
+}
diff --git a/scripts/list_image.sh b/scripts/list_image.sh
new file mode 100755
index 0000000..0542fa6
--- /dev/null
+++ b/scripts/list_image.sh
@@ -0,0 +1,51 @@
+#! /bin/bash
+
+# Recursively list Android image directory.
+set -eu
+set -o pipefail
+
+function die() { format=$1; shift; printf "$format\n" "$@"; exit 1; }
+
+# Figure out the filer utility.
+declare filer=
+[[ -z "${ANDROID_HOST_OUT:-}" ]] || filer=${ANDROID_HOST_OUT}/bin/debugfs_static
+if [[ "${1:-}" =~ --debugfs_path=(.*) ]]; then
+ filer=${BASH_REMATCH[1]}
+ shift
+fi
+if [[ -z "${filer:-}" ]]; then
+ maybefiler="$(dirname $0)/debugfs_static"
+ [[ ! -x "$maybefiler" ]] || filer="$maybefiler"
+fi
+
+(( $# >0 )) || die "%s [--debugfs_path=<path>] IMAGE" "$0"
+
+[[ -n "${filer:-}" ]] || die "cannot locate 'debugfs' executable: \
+--debugfs_path= is missing, ANDROID_HOST_OUT is not set, \
+and 'debugfs_static' is not colocated with this script"
+declare -r image="$1"
+
+function dolevel() {
+ printf "%s/\n" "$1"
+ # Each line of the file output consists of 6 fields separated with '/'.
+ # The second one contains the file's attributes, and the fifth its name.
+ $filer -R "ls -l -p $1" "$image" 2>/dev/null |\
+ sed -nr 's|^/.*/(.*)/.*/.*/(.+)/.*/$|\2 \1|p' | LANG=C sort | \
+ while read name attr; do
+ [[ "$name" != '.' && "$name" != '..' ]] || continue
+ path="$1/$name"
+ # If the second char of the attributes is '4', it is a directory.
+ if [[ $attr =~ ^.4 ]]; then
+ dolevel "$path"
+ else
+ printf "%s\n" "$path"
+ fi
+ done
+}
+
+# The filer always prints its version on stderr, so we are going
+# to redirect it to the bit bucket. On the other hand, the filer's
+# return code on error is still 0. Let's run it once to without
+# redirecting stderr to see that there is at least one entry.
+$filer -R "ls -l -p" "$image" | grep -q -m1 -P '^/.*/.*/.*/.*/.+/.*/$'
+dolevel .
diff --git a/scripts/test_config_fixer.py b/scripts/test_config_fixer.py
index c150e8c..3dbc22e 100644
--- a/scripts/test_config_fixer.py
+++ b/scripts/test_config_fixer.py
@@ -28,6 +28,8 @@
from manifest import parse_test_config
from manifest import write_xml
+KNOWN_PREPARERS = ['com.android.tradefed.targetprep.TestAppInstallSetup',
+ 'com.android.tradefed.targetprep.suite.SuiteApkInstaller']
def parse_args():
"""Parse commandline arguments."""
@@ -64,7 +66,7 @@
tests = get_children_with_tag(test_config, 'target_preparer')
for test in tests:
- if test.getAttribute('class') == "com.android.tradefed.targetprep.TestAppInstallSetup":
+ if test.getAttribute('class') in KNOWN_PREPARERS:
options = get_children_with_tag(test, 'option')
for option in options:
if option.getAttribute('name') == "test-file-name":
diff --git a/scripts/test_config_fixer_test.py b/scripts/test_config_fixer_test.py
index d00a593..39ce5b3 100644
--- a/scripts/test_config_fixer_test.py
+++ b/scripts/test_config_fixer_test.py
@@ -70,7 +70,7 @@
class OverwriteTestFileNameTest(unittest.TestCase):
""" Unit tests for overwrite_test_file_name function """
- test_config = (
+ test_config_test_app_install_setup = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<configuration description="Runs some tests.">\n'
' <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">\n'
@@ -82,15 +82,38 @@
' </test>\n'
'</configuration>\n')
- def test_all(self):
- doc = minidom.parseString(self.test_config % ("foo.apk"))
+ test_config_suite_apk_installer = (
+ '<?xml version="1.0" encoding="utf-8"?>\n'
+ '<configuration description="Runs some tests.">\n'
+ ' <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">\n'
+ ' <option name="test-file-name" value="%s"/>\n'
+ ' </target_preparer>\n'
+ ' <test class="com.android.tradefed.testtype.AndroidJUnitTest">\n'
+ ' <option name="package" value="com.android.foo"/>\n'
+ ' <option name="runtime-hint" value="20s"/>\n'
+ ' </test>\n'
+ '</configuration>\n')
+
+ def test_testappinstallsetup(self):
+ doc = minidom.parseString(self.test_config_test_app_install_setup % ("foo.apk"))
test_config_fixer.overwrite_test_file_name(doc, "bar.apk")
output = io.StringIO()
test_config_fixer.write_xml(output, doc)
# Only the matching package name in a test node should be updated.
- expected = self.test_config % ("bar.apk")
+ expected = self.test_config_test_app_install_setup % ("bar.apk")
+ self.assertEqual(expected, output.getvalue())
+
+ def test_suiteapkinstaller(self):
+ doc = minidom.parseString(self.test_config_suite_apk_installer % ("foo.apk"))
+
+ test_config_fixer.overwrite_test_file_name(doc, "bar.apk")
+ output = io.StringIO()
+ test_config_fixer.write_xml(output, doc)
+
+ # Only the matching package name in a test node should be updated.
+ expected = self.test_config_suite_apk_installer % ("bar.apk")
self.assertEqual(expected, output.getvalue())
diff --git a/ui/build/build.go b/ui/build/build.go
index d261f89..aadf4af 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -18,6 +18,7 @@
"io/ioutil"
"os"
"path/filepath"
+ "sync"
"text/template"
"android/soong/ui/metrics"
@@ -205,6 +206,8 @@
return
}
+ defer waitForDist(ctx)
+
// checkProblematicFiles aborts the build if Android.mk or CleanSpec.mk are found at the root of the tree.
checkProblematicFiles(ctx)
@@ -329,8 +332,18 @@
}
}
+var distWaitGroup sync.WaitGroup
+
+// waitForDist waits for all backgrounded distGzipFile and distFile writes to finish
+func waitForDist(ctx Context) {
+ ctx.BeginTrace("soong_ui", "dist")
+ defer ctx.EndTrace()
+
+ distWaitGroup.Wait()
+}
+
// distGzipFile writes a compressed copy of src to the distDir if dist is enabled. Failures
-// are printed but non-fatal.
+// are printed but non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
func distGzipFile(ctx Context, config Config, src string, subDirs ...string) {
if !config.Dist() {
return
@@ -343,13 +356,17 @@
ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
}
- if err := gzipFileToDir(src, destDir); err != nil {
- ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
- }
+ distWaitGroup.Add(1)
+ go func() {
+ defer distWaitGroup.Done()
+ if err := gzipFileToDir(src, destDir); err != nil {
+ ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
+ }
+ }()
}
// distFile writes a copy of src to the distDir if dist is enabled. Failures are printed but
-// non-fatal.
+// non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
func distFile(ctx Context, config Config, src string, subDirs ...string) {
if !config.Dist() {
return
@@ -362,7 +379,11 @@
ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
}
- if _, err := copyFile(src, filepath.Join(destDir, filepath.Base(src))); err != nil {
- ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
- }
+ distWaitGroup.Add(1)
+ go func() {
+ defer distWaitGroup.Done()
+ if _, err := copyFile(src, filepath.Join(destDir, filepath.Base(src))); err != nil {
+ ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
+ }
+ }()
}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index c7f22f9..8992b4f 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -15,7 +15,9 @@
package build
import (
+ "errors"
"fmt"
+ "io/fs"
"io/ioutil"
"os"
"path/filepath"
@@ -491,10 +493,14 @@
ninja("bootstrap", "bootstrap.ninja", targets...)
- var soongBuildMetrics *soong_metrics_proto.SoongBuildMetrics
if shouldCollectBuildSoongMetrics(config) {
soongBuildMetrics := loadSoongBuildMetrics(ctx, config)
- logSoongBuildMetrics(ctx, soongBuildMetrics)
+ if soongBuildMetrics != nil {
+ logSoongBuildMetrics(ctx, soongBuildMetrics)
+ if ctx.Metrics != nil {
+ ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
+ }
+ }
}
distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
@@ -504,9 +510,6 @@
distGzipFile(ctx, config, config.SoongMakeVarsMk(), "soong")
}
- if shouldCollectBuildSoongMetrics(config) && ctx.Metrics != nil {
- ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
- }
if config.JsonModuleGraph() {
distGzipFile(ctx, config, config.ModuleGraphFile(), "soong")
}
@@ -538,8 +541,12 @@
func loadSoongBuildMetrics(ctx Context, config Config) *soong_metrics_proto.SoongBuildMetrics {
soongBuildMetricsFile := filepath.Join(config.LogsDir(), "soong_build_metrics.pb")
- buf, err := ioutil.ReadFile(soongBuildMetricsFile)
- if err != nil {
+ buf, err := os.ReadFile(soongBuildMetricsFile)
+ if errors.Is(err, fs.ErrNotExist) {
+ // Soong may not have run during this invocation
+ ctx.Verbosef("Failed to read metrics file, %s: %s", soongBuildMetricsFile, err)
+ return nil
+ } else if err != nil {
ctx.Fatalf("Failed to load %s: %s", soongBuildMetricsFile, err)
}
soongBuildMetrics := &soong_metrics_proto.SoongBuildMetrics{}