diff options
| -rw-r--r-- | android/api_levels.go | 2 | ||||
| -rw-r--r-- | android/arch.go | 10 | ||||
| -rw-r--r-- | android/bazel.go | 1 | ||||
| -rw-r--r-- | android/config.go | 4 | ||||
| -rw-r--r-- | android/variable.go | 9 | ||||
| -rw-r--r-- | apex/androidmk.go | 6 | ||||
| -rw-r--r-- | apex/apex.go | 2 | ||||
| -rw-r--r-- | apex/apex_test.go | 10 | ||||
| -rw-r--r-- | apex/builder.go | 4 | ||||
| -rw-r--r-- | bp2build/Android.bp | 7 | ||||
| -rw-r--r-- | bp2build/android_app_conversion_test.go | 6 | ||||
| -rw-r--r-- | bp2build/java_proto_conversion_test.go | 6 | ||||
| -rw-r--r-- | cc/cc.go | 2 | ||||
| -rw-r--r-- | cc/cc_test.go | 4 | ||||
| -rw-r--r-- | cc/config/toolchain.go | 9 | ||||
| -rw-r--r-- | cc/coverage.go | 10 | ||||
| -rw-r--r-- | cc/sanitize_test.go | 6 | ||||
| -rw-r--r-- | cc/testing.go | 76 | ||||
| -rw-r--r-- | cc/vendor_snapshot.go | 2 | ||||
| -rw-r--r-- | cc/vndk.go | 2 | ||||
| -rw-r--r-- | dexpreopt/DEXPREOPT_IMPLEMENTATION.md | 258 | ||||
| -rw-r--r-- | java/base.go | 16 | ||||
| -rw-r--r-- | java/bootclasspath_fragment.go | 31 | ||||
| -rw-r--r-- | java/java.go | 5 | ||||
| -rw-r--r-- | rust/compiler.go | 7 | ||||
| -rw-r--r-- | rust/config/toolchain.go | 9 | ||||
| -rw-r--r-- | rust/coverage.go | 5 | ||||
| -rw-r--r-- | rust/image.go | 4 | ||||
| -rw-r--r-- | rust/rust.go | 1 | ||||
| -rw-r--r-- | rust/testing.go | 4 | ||||
| -rw-r--r-- | rust/vendor_snapshot_test.go | 25 |
31 files changed, 413 insertions, 130 deletions
diff --git a/android/api_levels.go b/android/api_levels.go index 926d29794..de566250c 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -321,6 +321,7 @@ func getFinalCodenamesMap(config Config) map[string]int { "Q": 29, "R": 30, "S": 31, + "S-V2": 32, } // TODO: Differentiate "current" and "future". @@ -364,6 +365,7 @@ func GetApiLevelsMap(config Config) map[string]int { "Q": 29, "R": 30, "S": 31, + "S-V2": 32, } for i, codename := range config.PlatformVersionActiveCodenames() { apiLevelsMap[codename] = previewAPILevelBase + i diff --git a/android/arch.go b/android/arch.go index 8aa8d4043..a7c62a915 100644 --- a/android/arch.go +++ b/android/arch.go @@ -2179,6 +2179,16 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } + if os == LinuxMusl { + targetField := "Musl_" + arch.Name + targetStructs := getTargetStructs(ctx, archProperties, targetField) + osArchStructs = append(osArchStructs, targetStructs...) + } + if os == Linux { + targetField := "Glibc_" + arch.Name + targetStructs := getTargetStructs(ctx, archProperties, targetField) + osArchStructs = append(osArchStructs, targetStructs...) + } targetField := GetCompoundTargetField(os, arch) targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name) diff --git a/android/bazel.go b/android/bazel.go index 86339ab3f..342b840da 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -293,6 +293,7 @@ var ( "development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue, "development/sdk": Bp2BuildDefaultTrueRecursively, "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively, + "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively, "external/auto/common": Bp2BuildDefaultTrueRecursively, "external/auto/service": Bp2BuildDefaultTrueRecursively, "external/boringssl": Bp2BuildDefaultTrueRecursively, diff --git a/android/config.go b/android/config.go index 3d8bc31a5..e8ca84c6f 100644 --- a/android/config.go +++ b/android/config.go @@ -1256,6 +1256,10 @@ func (c *deviceConfig) ClangCoverageEnabled() bool { return Bool(c.config.productVariables.ClangCoverage) } +func (c *deviceConfig) ClangCoverageContinuousMode() bool { + return Bool(c.config.productVariables.ClangCoverageContinuousMode) +} + func (c *deviceConfig) GcovCoverageEnabled() bool { return Bool(c.config.productVariables.GcovCoverage) } diff --git a/android/variable.go b/android/variable.go index 68f19b993..37037ebdb 100644 --- a/android/variable.go +++ b/android/variable.go @@ -306,10 +306,11 @@ type productVariables struct { JavaCoveragePaths []string `json:",omitempty"` JavaCoverageExcludePaths []string `json:",omitempty"` - GcovCoverage *bool `json:",omitempty"` - ClangCoverage *bool `json:",omitempty"` - NativeCoveragePaths []string `json:",omitempty"` - NativeCoverageExcludePaths []string `json:",omitempty"` + GcovCoverage *bool `json:",omitempty"` + ClangCoverage *bool `json:",omitempty"` + NativeCoveragePaths []string `json:",omitempty"` + NativeCoverageExcludePaths []string `json:",omitempty"` + ClangCoverageContinuousMode *bool `json:",omitempty"` // Set by NewConfig Native_coverage *bool `json:",omitempty"` diff --git a/apex/androidmk.go b/apex/androidmk.go index 8785ca0f3..059b4d76c 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -373,8 +373,10 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { } fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+stemSuffix) fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable()) - fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String()) - fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String()) + if a.installable() { + fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String()) + fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String()) + } // Because apex writes .mk with Custom(), we need to write manually some common properties // which are available via data.Entries diff --git a/apex/apex.go b/apex/apex.go index 9031a4ea9..ac67feea2 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1415,7 +1415,7 @@ func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext for _, target := range ctx.MultiTargets() { if target.Arch.ArchType.Multilib == "lib64" { addDependenciesForNativeModules(ctx, ApexNativeDependencies{ - Native_shared_libs: []string{"libclang_rt.hwasan-aarch64-android"}, + Native_shared_libs: []string{"libclang_rt.hwasan"}, Tests: nil, Jni_libs: nil, Binaries: nil, diff --git a/apex/apex_test.go b/apex/apex_test.go index 1c36c759f..4f2a58348 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -1415,13 +1415,14 @@ func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) { } cc_prebuilt_library_shared { - name: "libclang_rt.hwasan-aarch64-android", + name: "libclang_rt.hwasan", no_libcrt: true, nocrt: true, stl: "none", system_shared_libs: [], srcs: [""], stubs: { versions: ["1"] }, + stem: "libclang_rt.hwasan-aarch64-android", sanitize: { never: true, @@ -1434,7 +1435,7 @@ func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) { "lib64/bionic/libclang_rt.hwasan-aarch64-android.so", }) - hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared") + hwasan := ctx.ModuleForTests("libclang_rt.hwasan", "android_arm64_armv8-a_shared") installed := hwasan.Description("install libclang_rt.hwasan") ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so") @@ -1462,13 +1463,14 @@ func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) { } cc_prebuilt_library_shared { - name: "libclang_rt.hwasan-aarch64-android", + name: "libclang_rt.hwasan", no_libcrt: true, nocrt: true, stl: "none", system_shared_libs: [], srcs: [""], stubs: { versions: ["1"] }, + stem: "libclang_rt.hwasan-aarch64-android", sanitize: { never: true, @@ -1482,7 +1484,7 @@ func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) { "lib64/bionic/libclang_rt.hwasan-aarch64-android.so", }) - hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared") + hwasan := ctx.ModuleForTests("libclang_rt.hwasan", "android_arm64_armv8-a_shared") installed := hwasan.Description("install libclang_rt.hwasan") ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so") diff --git a/apex/builder.go b/apex/builder.go index 183c21562..8c5f99bf5 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -856,6 +856,10 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { installSuffix = imageCapexSuffix } + if !a.installable() { + a.SkipInstall() + } + // Install to $OUT/soong/{target,host}/.../apex. a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile, a.compatSymlinks.Paths()...) diff --git a/bp2build/Android.bp b/bp2build/Android.bp index b904c3533..8a171d402 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -44,9 +44,16 @@ bootstrap_go_package { "cc_library_shared_conversion_test.go", "cc_library_static_conversion_test.go", "cc_object_conversion_test.go", + "cc_prebuilt_library_shared_test.go", "conversion_test.go", "filegroup_conversion_test.go", "genrule_conversion_test.go", + "java_binary_host_conversion_test.go", + "java_import_conversion_test.go", + "java_library_conversion_test.go", + "java_library_host_conversion_test.go", + "java_plugin_conversion_test.go", + "java_proto_conversion_test.go", "performance_test.go", "prebuilt_etc_conversion_test.go", "python_binary_conversion_test.go", diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go index 28de06c00..42c1a5458 100644 --- a/bp2build/android_app_conversion_test.go +++ b/bp2build/android_app_conversion_test.go @@ -51,6 +51,7 @@ android_app { "srcs": `["app.java"]`, "manifest": `"AndroidManifest.xml"`, "resource_files": `["res/res.png"]`, + "deps": `["//prebuilts/sdk:public_current_android_sdk_java_import"]`, }), }}) } @@ -86,7 +87,10 @@ android_app { "resb/res.png", ]`, "custom_package": `"com.google"`, - "deps": `[":static_lib_dep"]`, + "deps": `[ + "//prebuilts/sdk:public_current_android_sdk_java_import", + ":static_lib_dep", + ]`, }), }}) } diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go index 93b0677a6..61a398cd9 100644 --- a/bp2build/java_proto_conversion_test.go +++ b/bp2build/java_proto_conversion_test.go @@ -71,8 +71,7 @@ func TestJavaProto(t *testing.T) { }` protoLibrary := makeBazelTarget("proto_library", "java-protos_proto", attrNameToString{ - "srcs": `["a.proto"]`, - "strip_import_prefix": `""`, + "srcs": `["a.proto"]`, }) for _, tc := range testCases { @@ -107,8 +106,7 @@ func TestJavaProtoDefault(t *testing.T) { `, expectedBazelTargets: []string{ makeBazelTarget("proto_library", "java-protos_proto", attrNameToString{ - "srcs": `["a.proto"]`, - "strip_import_prefix": `""`, + "srcs": `["a.proto"]`, }), makeBazelTarget( "java_lite_proto_library", @@ -1383,7 +1383,7 @@ func isBionic(name string) bool { } func InstallToBootstrap(name string, config android.Config) bool { - if name == "libclang_rt.hwasan-aarch64-android" { + if name == "libclang_rt.hwasan" { return true } return isBionic(name) diff --git a/cc/cc_test.go b/cc/cc_test.go index 51a6a271f..278efa174 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -2944,13 +2944,13 @@ func TestStaticLibDepExport(t *testing.T) { // Check the shared version of lib2. variant := "android_arm64_armv8-a_shared" module := ctx.ModuleForTests("lib2", variant).Module().(*Module) - checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins-aarch64-android"}, module) + checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins"}, module) // Check the static version of lib2. variant = "android_arm64_armv8-a_static" module = ctx.ModuleForTests("lib2", variant).Module().(*Module) // libc++_static is linked additionally. - checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins-aarch64-android"}, module) + checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins"}, module) } var compilerFlagsTestCases = []struct { diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go index 6cede11a0..7175fdc1a 100644 --- a/cc/config/toolchain.go +++ b/cc/config/toolchain.go @@ -227,14 +227,7 @@ func addPrefix(list []string, prefix string) []string { } func LibclangRuntimeLibrary(t Toolchain, library string) string { - arch := t.LibclangRuntimeLibraryArch() - if arch == "" { - return "" - } - if !t.Bionic() { - return "libclang_rt." + library + "-" + arch - } - return "libclang_rt." + library + "-" + arch + "-android" + return "libclang_rt." + library } func BuiltinsRuntimeLibrary(t Toolchain) string { diff --git a/cc/coverage.go b/cc/coverage.go index f2b5425e6..d0902eab8 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -77,6 +77,10 @@ func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps { return deps } +func EnableContinuousCoverage(ctx android.BaseModuleContext) bool { + return ctx.DeviceConfig().ClangCoverageContinuousMode() +} + func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) { clangCoverage := ctx.DeviceConfig().ClangCoverageEnabled() gcovCoverage := ctx.DeviceConfig().GcovCoverageEnabled() @@ -101,6 +105,9 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags // Override -Wframe-larger-than. We can expect frame size increase after // coverage instrumentation. flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=") + if EnableContinuousCoverage(ctx) { + flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-runtime-counter-relocation") + } } } @@ -152,6 +159,9 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,getenv") } else if clangCoverage { flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrFlag) + if EnableContinuousCoverage(ctx) { + flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm=-runtime-counter-relocation") + } coverage := ctx.GetDirectDepWithTag(getClangProfileLibraryName(ctx), CoverageDepTag).(*Module) deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path()) diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go index 0070e4026..c1ca03408 100644 --- a/cc/sanitize_test.go +++ b/cc/sanitize_test.go @@ -24,11 +24,7 @@ import ( var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(` cc_library_shared { - name: "libclang_rt.asan-aarch64-android", - } - - cc_library_shared { - name: "libclang_rt.asan-arm-android", + name: "libclang_rt.asan", } `)) diff --git a/cc/testing.go b/cc/testing.go index a03d147a0..32f7c6080 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -86,51 +86,17 @@ func commonDefaultModules() string { } cc_prebuilt_library_static { - name: "libclang_rt.builtins-arm-android", + name: "libclang_rt.builtins", defaults: ["toolchain_libs_defaults"], - native_bridge_supported: true, + host_supported: true, + vendor_available: true, vendor_ramdisk_available: true, - } - - cc_prebuilt_library_static { - name: "libclang_rt.builtins-aarch64-android", - defaults: ["toolchain_libs_defaults"], native_bridge_supported: true, - vendor_ramdisk_available: true, - } - - cc_prebuilt_library_static { - name: "libclang_rt.builtins-x86_64", - defaults: ["toolchain_libs_defaults"], - host_supported: true, - } - - cc_prebuilt_library_static { - name: "libclang_rt.builtins-i386", - defaults: ["toolchain_libs_defaults"], - host_supported: true, } cc_prebuilt_library_shared { - name: "libclang_rt.hwasan-aarch64-android", - defaults: ["toolchain_libs_defaults"], - } - - cc_prebuilt_library_static { - name: "libclang_rt.builtins-i686-android", + name: "libclang_rt.hwasan", defaults: ["toolchain_libs_defaults"], - vendor_ramdisk_available: true, - native_bridge_supported: true, - } - - cc_prebuilt_library_static { - name: "libclang_rt.builtins-x86_64-android", - defaults: [ - "linux_bionic_supported", - "toolchain_libs_defaults", - ], - native_bridge_supported: true, - vendor_ramdisk_available: true, } cc_prebuilt_library_static { @@ -144,30 +110,7 @@ func commonDefaultModules() string { } cc_prebuilt_library_static { - name: "libclang_rt.fuzzer-arm-android", - defaults: ["toolchain_libs_defaults"], - } - - cc_prebuilt_library_static { - name: "libclang_rt.fuzzer-aarch64-android", - defaults: ["toolchain_libs_defaults"], - } - - cc_prebuilt_library_static { - name: "libclang_rt.fuzzer-i686-android", - defaults: ["toolchain_libs_defaults"], - } - - cc_prebuilt_library_static { - name: "libclang_rt.fuzzer-x86_64-android", - defaults: [ - "linux_bionic_supported", - "toolchain_libs_defaults", - ], - } - - cc_prebuilt_library_static { - name: "libclang_rt.fuzzer-x86_64", + name: "libclang_rt.fuzzer", defaults: [ "linux_bionic_supported", "toolchain_libs_defaults", @@ -176,17 +119,12 @@ func commonDefaultModules() string { // Needed for sanitizer cc_prebuilt_library_shared { - name: "libclang_rt.ubsan_standalone-aarch64-android", - defaults: ["toolchain_libs_defaults"], - } - - cc_prebuilt_library_static { - name: "libclang_rt.ubsan_minimal-aarch64-android", + name: "libclang_rt.ubsan_standalone", defaults: ["toolchain_libs_defaults"], } cc_prebuilt_library_static { - name: "libclang_rt.ubsan_minimal-arm-android", + name: "libclang_rt.ubsan_minimal", defaults: ["toolchain_libs_defaults"], } diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 8a17e2e54..e7c05aca8 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -146,6 +146,7 @@ type snapshotJsonFlags struct { // binary flags Symlinks []string `json:",omitempty"` StaticExecutable bool `json:",omitempty"` + InstallInRoot bool `json:",omitempty"` // dependencies SharedLibs []string `json:",omitempty"` @@ -320,6 +321,7 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS // binary flags prop.Symlinks = m.Symlinks() prop.StaticExecutable = m.StaticExecutable() + prop.InstallInRoot = m.InstallInRoot() prop.SharedLibs = m.SnapshotSharedLibs() // static libs dependencies are required to collect the NOTICE files. prop.StaticLibs = m.SnapshotStaticLibs() diff --git a/cc/vndk.go b/cc/vndk.go index c9c9f2c08..bf6148b1c 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -450,7 +450,7 @@ var _ android.OutputFileProducer = &vndkLibrariesTxt{} // Therefore, by removing the library here, we cause it to only be installed if libc // depends on it. func llndkLibrariesTxtFactory() android.SingletonModule { - return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan-") + return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan") } // vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries diff --git a/dexpreopt/DEXPREOPT_IMPLEMENTATION.md b/dexpreopt/DEXPREOPT_IMPLEMENTATION.md new file mode 100644 index 000000000..c3a17307d --- /dev/null +++ b/dexpreopt/DEXPREOPT_IMPLEMENTATION.md @@ -0,0 +1,258 @@ +## Dexpreopt implementation + +### Introduction + +All dexpreopted Java code falls into three categories: + +- bootclasspath +- system server +- apps and libraries + +Dexpreopt implementation for bootclasspath libraries (boot images) is located in +[soong/java] (see e.g. [soong/java/dexpreopt_bootjars.go]), and install rules +are in [make/core/dex_preopt.mk]. + +Dexpreopt implementation for system server, libraries and apps is located in +[soong/dexpreopt]. For the rest of this section we focus primarily on it (and +not boot images). + +Dexpeopt implementation is split across the Soong part and the Make part. The +core logic is in Soong, and Make only generates configs and scripts to pass +information to Soong. + +### Global and module dexpreopt.config + +The build system generates a global JSON dexpreopt config that is populated from +product variables. This is static configuration that is passed to both Soong and +Make. The `$OUT/soong/dexpreopt.config` file is generated in +[make/core/dex_preopt_config.mk]. Soong reads it in [soong/dexpreopt/config.go] +and makes a device-specific copy (this is needed to ensure incremental build +correctness). The global config contains lists of bootclasspath jars, system +server jars, dex2oat options, global switches that enable and disable parts of +dexpreopt and so on. + +The build system also generates a module config for each dexpreopted package. It +contains package-specific configuration that is derived from the global +configuration and Android.bp or Android.mk module for the package. + +Module configs for Make packages are generated in +[make/core/dex_preopt_odex_install.mk]; they are materialized as per-package +JSON dexpreopt.config files. + +Module configs in Soong are not materialized as dexpreopt.config files and exist +as Go structures in memory, unless it is necessary to materialize them as a file +for dependent Make packages or for post-dexpreopting. Module configs are defined +in [soong/dexpreopt/config.go]. + +### Dexpreopt in Soong + +The Soong implementation of dexpreopt consists roughly of the following steps: + +- Read global dexpreopt config passed from Make ([soong/dexpreopt/config.go]). + +- Construct a static boot image config ([soong/java/dexpreopt_config.go]). + +- During dependency mutator pass, for each suitable module: + - add uses-library dependencies (e.g. for apps: [soong/java/app.go:deps]) + +- During rule generation pass, for each suitable module: + - compute transitive uses-library dependency closure + ([soong/java/java.go:addCLCFromDep]) + + - construct CLC from the dependency closure + ([soong/dexpreopt/class_loader_context.go]) + + - construct module config with CLC, boot image locations, etc. + ([soong/java/dexpreopt.go]) + + - generate build rules to verify build-time CLC against the manifest (e.g. + for apps: [soong/java/app.go:verifyUsesLibraries]) + + - generate dexpreopt build rule ([soong/dexpreopt/dexpreopt.go]) + +- At the end of rule generation pass: + - generate build rules for boot images ([soong/java/dexpreopt_bootjars.go], + [soong/java/bootclasspath_fragment.go] and + [soong/java/platform_bootclasspath.go]) + +### Dexpreopt in Make - dexpreopt_gen + +In order to reuse the same dexpreopt implementation for both Soong and Make +packages, part of Soong is compiled into a standalone binary dexpreopt_gen. It +runs during the Ninja stage of the build and generates shell scripts with +dexpreopt build rules for Make packages, and then executes them. + +This setup causes many inconveniences. To name a few: + +- Errors in the build rules are only revealed at the late stage of the build. + +- These rules are not tested by the presubmit builds that run `m nothing` on + many build targets/products. + +- It is impossible to find dexpreopt build rules in the generated Ninja files. + +However all these issues are a lesser evil compared to having a duplicate +dexpreopt implementation in Make. Also note that it would be problematic to +reimplement the logic in Make anyway, because Android.mk modules are not +processed in the order of uses-library dependencies and propagating dependency +information from one module to another would require a similar workaround with +a script. + +Dexpreopt for Make packages involves a few steps: + +- At Soong phase (during `m nothing`), see dexpreopt_gen: + - generate build rules for dexpreopt_gen binary + +- At Make/Kati phase (during `m nothing`), see + [make/core/dex_preopt_odex_install.mk]: + - generate build rules for module dexpreopt.config + + - generate build rules for merging dependency dexpreopt.config files (see + [make/core/dex_preopt_config_merger.py]) + + - generate build rules for dexpreopt_gen invocation + + - generate build rules for executing dexpreopt.sh scripts + +- At Ninja phase (during `m`): + - generate dexpreopt.config files + + - execute dexpreopt_gen rules (generate dexpreopt.sh scripts) + + - execute dexpreopt.sh scripts (this runs the actual dexpreopt) + +The Make/Kati phase adds all the necessary dependencies that trigger +dexpreopt_gen and dexpreopt.sh rules. The real dexpreopt command (dex2oat +invocation that will be executed to AOT-compile a package) is in the +dexpreopt.sh script, which is generated close to the end of the build. + +### Indirect build rules + +The process described above for Make packages involves "indirect build rules", +i.e. build rules that are generated not at the time when the build system is +created (which is a small step at the very beginning of the build triggered with +`m nothing`), but at the time when the actual build is done (`m` phase). + +Some build systems, such as Make, allow modifications of the build graph during +the build. Other build systems, such as Soong, have a clear separation into the +first "generation phase" (this is when build rules are created) and the second +"build phase" (this is when the build rules are executed), and they do not allow +modifications of the dependency graph during the second phase. The Soong +approach is better from performance standpoint, because with the Make approach +there are no guarantees regarding the time of the build --- recursive build +graph modfications continue until fixpoint. However the Soong approach is also +more restictive, as it can only generate build rules from the information that +is passed to the build system via global configuration, Android.bp files or +encoded in the Go code. Any other information (such as the contents of the Java +manifest files) are not accessible and cannot be used to generate build rules. + +Hence the need for the "indirect build rules": during the generation phase only +stubs of the build rules are generated, and the real rules are generated by the +stub rules during the build phase (and executed immediately). Note that the +build system still has to add all the necessary dependencies during the +generation phase, because it will not be possible to change build order during +the build phase. + +Indirect buils rules are used in a couple of places in dexpreopt: + +- [soong/scripts/manifest_check.py]: first to extract targetSdkVersion from the + manifest, and later to extract `<uses-library/>` tags from the manifest and + compare them to the uses-library list known to the build system + +- [soong/scripts/construct_context.py]: to trim compatibility libraries in CLC + +- [make/core/dex_preopt_config_merger.py]: to merge information from + dexpreopt.config files for uses-library dependencies into the dependent's + dexpreopt.config file (mostly the CLC) + +- autogenerated dexpreopt.sh scripts: to call dexpreopt_gen + +### Consistency check - manifest_check.py + +Because the information from the manifests has to be duplicated in the +Android.bp/Android.mk files, there is a danger that it may get out of sync. To +guard against that, the build system generates a rule that verifies +uses-libraries: checks the metadata in the build files against the contents of a +manifest. The manifest can be available as a source file, or as part of a +prebuilt APK. + +The check is implemented in [soong/scripts/manifest_check.py]. + +It is possible to turn off the check globally for a product by setting +`PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true` in a product makefile, or for a +particular build by setting `RELAX_USES_LIBRARY_CHECK=true`. + +### Compatibility libraries - construct_context.py + +Compatibility libraries are libraries that didn’t exist prior to a certain SDK +version (say, `N`), but classes in them were in the bootclasspath jars, etc., +and in version `N` they have been separated into a standalone uses-library. +Compatibility libraries should only be in the CLC of an app if its +`targetSdkVersion` in the manifest is less than `N`. + +Currently compatibility libraries only affect apps (but not other libraries). + +The build system cannot see `targetSdkVersion` of an app at the time it +generates dexpreopt build rules, so it doesn't know whether to add compatibility +libaries to CLC or not. As a workaround, the build system includes all +compatibility libraries regardless of the app version, and appends some extra +logic to the dexpreopt rule that will extract `targetSdkVersion` from the +manifest and filter CLC based on that version during Ninja stage of the build, +immediately before executing the dexpreopt command (see the +soong/scripts/construct_context.py script). + +As of the time of writing (January 2022), there are the following compatibility +libraries: + +- org.apache.http.legacy (SDK 28) +- android.hidl.base-V1.0-java (SDK 29) +- android.hidl.manager-V1.0-java (SDK 29) +- android.test.base (SDK 30) +- android.test.mock (SDK 30) + +### Manifest fixer + +Sometimes uses-library tags are missing from the source manifest of a +library/app. This may happen for example if one of the transitive dependencies +of the library/app starts using another uses-library, and the library/app's +manifest isn't updated to include it. + +Soong can compute some of the missing uses-library tags for a given library/app +automatically as SDK libraries in the transitive dependency closure of the +library/app. The closure is needed because a library/app may depend on a static +library that may in turn depend on an SDK library (possibly transitively via +another library). + +Not all uses-library tags can be computed in this way, because some of the +uses-library dependencies are not SDK libraries, or they are not reachable via +transitive dependency closure. But when possible, allowing Soong to calculate +the manifest entries is less prone to errors and simplifies maintenance. For +example, consider a situation when many apps use some static library that adds a +new uses-library dependency -- all the apps will have to be updated. That is +difficult to maintain. + +There is also a manifest merger, because sometimes the final manifest of an app +is merged from a few dependency manifests, so the final manifest installed on +devices contains a superset of uses-library tags of the source manifest of the +app. + + +[make/core/dex_preopt.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt.mk +[make/core/dex_preopt_config.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_config.mk +[make/core/dex_preopt_config_merger.py]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_config_merger.py +[make/core/dex_preopt_odex_install.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_odex_install.mk +[soong/dexpreopt]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt +[soong/dexpreopt/class_loader_context.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/class_loader_context.go +[soong/dexpreopt/config.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/config.go +[soong/dexpreopt/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/dexpreopt.go +[soong/java]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java +[soong/java/app.go:deps]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20deps%22 +[soong/java/app.go:verifyUsesLibraries]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20verifyUsesLibraries%22 +[soong/java/bootclasspath_fragment.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/bootclasspath_fragment.go +[soong/java/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt.go +[soong/java/dexpreopt_bootjars.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt_bootjars.go +[soong/java/dexpreopt_config.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt_config.go +[soong/java/java.go:addCLCFromDep]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/java.go?q=%22func%20addCLCfromDep%22 +[soong/java/platform_bootclasspath.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/platform_bootclasspath.go +[soong/scripts/construct_context.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/scripts/construct_context.py +[soong/scripts/manifest_check.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/scripts/manifest_check.py diff --git a/java/base.go b/java/base.go index 8747039da..9978a66fc 100644 --- a/java/base.go +++ b/java/base.go @@ -481,6 +481,8 @@ type Module struct { sdkVersion android.SdkSpec minSdkVersion android.SdkSpec maxSdkVersion android.SdkSpec + + sourceExtensions []string } func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error { @@ -982,6 +984,14 @@ func (j *Module) collectJavacFlags( return flags } +func (j *Module) AddJSONData(d *map[string]interface{}) { + (&j.ModuleBase).AddJSONData(d) + (*d)["Java"] = map[string]interface{}{ + "SourceExtensions": j.sourceExtensions, + } + +} + func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs) @@ -993,6 +1003,12 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs) + j.sourceExtensions = []string{} + for _, ext := range []string{".kt", ".proto", ".aidl", ".java", ".logtags"} { + if hasSrcExt(srcFiles.Strings(), ext) { + j.sourceExtensions = append(j.sourceExtensions, ext) + } + } if hasSrcExt(srcFiles.Strings(), ".proto") { flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags) } diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 5fe409e25..eddcb61f9 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -16,6 +16,7 @@ package java import ( "fmt" + "io" "path/filepath" "reflect" "strings" @@ -588,6 +589,19 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // Provide the apex content info. b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFilesByArch) } + } else { + // Versioned fragments are not needed by make. + b.HideFromMake() + } + + // In order for information about bootclasspath_fragment modules to be added to module-info.json + // it is necessary to output an entry to Make. As bootclasspath_fragment modules are part of an + // APEX there can be multiple variants, including the default/platform variant and only one can + // be output to Make but it does not really matter which variant is output. The default/platform + // variant is the first (ctx.PrimaryModule()) and is usually hidden from make so this just picks + // the last variant (ctx.FinalModule()). + if ctx.Module() != ctx.FinalModule() { + b.HideFromMake() } } @@ -849,7 +863,22 @@ func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android. } func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries { - var entriesList []android.AndroidMkEntries + // Use the generated classpath proto as the output. + outputFile := b.outputFilepath + // Create a fake entry that will cause this to be added to the module-info.json file. + entriesList := []android.AndroidMkEntries{{ + Class: "FAKE", + OutputFile: android.OptionalPathForPath(outputFile), + Include: "$(BUILD_PHONY_PACKAGE)", + ExtraFooters: []android.AndroidMkExtraFootersFunc{ + func(w io.Writer, name, prefix, moduleDir string) { + // Allow the bootclasspath_fragment to be built by simply passing its name on the command + // line. + fmt.Fprintln(w, ".PHONY:", b.Name()) + fmt.Fprintln(w, b.Name()+":", outputFile.String()) + }, + }, + }} for _, install := range b.bootImageDeviceInstalls { entriesList = append(entriesList, install.ToMakeEntries()) } diff --git a/java/java.go b/java/java.go index d0f0abc7a..0a35908dd 100644 --- a/java/java.go +++ b/java/java.go @@ -2030,6 +2030,11 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) } var deps bazel.LabelList + sdkVersion := m.SdkVersion(ctx) + if sdkVersion.Kind == android.SdkPublic && sdkVersion.ApiLevel == android.FutureApiLevel { + // TODO(b/220869005) remove forced dependency on current public android.jar + deps.Add(&bazel.Label{Label: "//prebuilts/sdk:public_current_android_sdk_java_import"}) + } if m.properties.Libs != nil { deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs)) } diff --git a/rust/compiler.go b/rust/compiler.go index c5d40f4dc..19499fa36 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -121,6 +121,12 @@ type BaseCompilerProperties struct { // include all of the static libraries symbols in any dylibs or binaries which use this rlib as well. Whole_static_libs []string `android:"arch_variant"` + // list of Rust system library dependencies. + // + // This is usually only needed when `no_stdlibs` is true, in which case it can be used to depend on system crates + // like `core` and `alloc`. + Stdlibs []string `android:"arch_variant"` + // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider // modules which create library variants (rust_bindgen). This must be the expected extern crate name used in // source, and is required to conform to an enforced format matching library output files (if the output file is @@ -360,6 +366,7 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...) deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...) deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...) + deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs...) if !Bool(compiler.Properties.No_stdlibs) { for _, stdlib := range config.Stdlibs { diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go index a769f121c..9c9d5724a 100644 --- a/rust/config/toolchain.go +++ b/rust/config/toolchain.go @@ -121,14 +121,7 @@ func LibFuzzerRuntimeLibrary(t Toolchain) string { } func LibclangRuntimeLibrary(t Toolchain, library string) string { - arch := t.LibclangRuntimeLibraryArch() - if arch == "" { - return "" - } - if !t.Bionic() { - return "libclang_rt." + library + "-" + arch - } - return "libclang_rt." + library + "-" + arch + "-android" + return "libclang_rt." + library } func LibRustRuntimeLibrary(t Toolchain, library string) string { diff --git a/rust/coverage.go b/rust/coverage.go index 050b811c7..651ce6e16 100644 --- a/rust/coverage.go +++ b/rust/coverage.go @@ -22,6 +22,7 @@ import ( var CovLibraryName = "libprofile-clang-extras" +// Add '%c' to default specifier after we resolve http://b/210012154 const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw" type coverage struct { @@ -59,6 +60,10 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags flags.LinkFlags = append(flags.LinkFlags, profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open") deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path()) + if cc.EnableContinuousCoverage(ctx) { + flags.RustFlags = append(flags.RustFlags, "-C llvm-args=--runtime-counter-relocation") + flags.LinkFlags = append(flags.LinkFlags, "-Wl,-mllvm,-runtime-counter-relocation") + } } return flags, deps diff --git a/rust/image.go b/rust/image.go index 5d57f1522..dfc7f7431 100644 --- a/rust/image.go +++ b/rust/image.go @@ -149,6 +149,10 @@ func (mod *Module) InRecovery() bool { return mod.ModuleBase.InRecovery() || mod.ModuleBase.InstallInRecovery() } +func (mod *Module) InRamdisk() bool { + return mod.ModuleBase.InRamdisk() || mod.ModuleBase.InstallInRamdisk() +} + func (mod *Module) InVendorRamdisk() bool { return mod.ModuleBase.InVendorRamdisk() || mod.ModuleBase.InstallInVendorRamdisk() } diff --git a/rust/rust.go b/rust/rust.go index f40f1a8bb..1c718a414 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -968,6 +968,7 @@ func (mod *Module) deps(ctx DepsContext) Deps { deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros) deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs) deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs) + deps.Stdlibs = android.LastUniqueStrings(deps.Stdlibs) deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs) return deps diff --git a/rust/testing.go b/rust/testing.go index 1b34dfe8e..cb98bed65 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -88,13 +88,13 @@ func GatherRequiredDepsForTest() string { export_include_dirs: ["libprotobuf-cpp-full-includes"], } cc_library { - name: "libclang_rt.asan-aarch64-android", + name: "libclang_rt.asan", no_libcrt: true, nocrt: true, system_shared_libs: [], } cc_library { - name: "libclang_rt.hwasan_static-aarch64-android", + name: "libclang_rt.hwasan_static", no_libcrt: true, nocrt: true, system_shared_libs: [], diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go index 03bd867a3..7be00425e 100644 --- a/rust/vendor_snapshot_test.go +++ b/rust/vendor_snapshot_test.go @@ -561,7 +561,7 @@ func TestVendorSnapshotUse(t *testing.T) { static_libs: [ "libvendor", "libvndk", - "libclang_rt.builtins-aarch64-android", + "libclang_rt.builtins", "note_memtag_heap_sync", ], shared_libs: [ @@ -589,7 +589,7 @@ func TestVendorSnapshotUse(t *testing.T) { static_libs: [ "libvendor", "libvndk", - "libclang_rt.builtins-arm-android", + "libclang_rt.builtins", ], shared_libs: [ "libvendor_available", @@ -731,19 +731,7 @@ func TestVendorSnapshotUse(t *testing.T) { } vendor_snapshot_static { - name: "libclang_rt.builtins-aarch64-android", - version: "30", - target_arch: "arm64", - vendor: true, - arch: { - arm64: { - src: "libclang_rt.builtins-aarch64-android.a", - }, - }, - } - - vendor_snapshot_static { - name: "libclang_rt.builtins-arm-android", + name: "libclang_rt.builtins", version: "30", target_arch: "arm64", vendor: true, @@ -751,6 +739,9 @@ func TestVendorSnapshotUse(t *testing.T) { arm: { src: "libclang_rt.builtins-arm-android.a", }, + arm64: { + src: "libclang_rt.builtins-aarch64-android.a", + }, }, } @@ -967,7 +958,7 @@ func TestVendorSnapshotUse(t *testing.T) { } libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs - if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot", "libclang_rt.builtins-aarch64-android.vendor"}; !reflect.DeepEqual(g, w) { + if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot", "libclang_rt.builtins.vendor"}; !reflect.DeepEqual(g, w) { t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g) } @@ -1024,7 +1015,7 @@ func TestVendorSnapshotUse(t *testing.T) { } memtagStaticLibs := ctx.ModuleForTests("memtag_binary", "android_vendor.30_arm64_armv8-a").Module().(*Module).Properties.AndroidMkStaticLibs - if g, w := memtagStaticLibs, []string{"libclang_rt.builtins-aarch64-android.vendor", "note_memtag_heap_sync.vendor"}; !reflect.DeepEqual(g, w) { + if g, w := memtagStaticLibs, []string{"libclang_rt.builtins.vendor", "note_memtag_heap_sync.vendor"}; !reflect.DeepEqual(g, w) { t.Errorf("wanted memtag_binary AndroidMkStaticLibs %q, got %q", w, g) } } |