Merge "soong: move -Wimplicit-fallthrough from cflags to cxxflags"
diff --git a/android/config.go b/android/config.go
index 63994e6..1e5a24d 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1087,6 +1087,10 @@
return c.productVariables.EnforceSystemCertificateWhitelist
}
+func (c *config) EnforceProductPartitionInterface() bool {
+ return Bool(c.productVariables.EnforceProductPartitionInterface)
+}
+
func (c *config) ProductHiddenAPIStubs() []string {
return c.productVariables.ProductHiddenAPIStubs
}
diff --git a/android/variable.go b/android/variable.go
index abbdf21..25a5dc0 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -309,6 +309,8 @@
TargetFSConfigGen []string `json:",omitempty"`
MissingUsesLibraries []string `json:",omitempty"`
+
+ EnforceProductPartitionInterface *bool `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/apex/apex.go b/apex/apex.go
index d77670a..f03a8f9 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -652,6 +652,7 @@
testApex bool
vndkApex bool
+ artApex bool
primaryApexType bool
// intermediate path for apex_manifest.json
@@ -1216,7 +1217,7 @@
if am, ok := child.(android.ApexModule); ok {
// We cannot use a switch statement on `depTag` here as the checked
// tags used below are private (e.g. `cc.sharedDepTag`).
- if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
+ if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) || java.IsJniDepTag(depTag) {
if cc, ok := child.(*cc.Module); ok {
if android.InList(cc.Name(), providedNativeSharedLibs) {
// If we're using a shared library which is provided from other APEX,
@@ -1261,6 +1262,19 @@
return false
})
+ // Specific to the ART apex: dexpreopt artifacts for libcore Java libraries.
+ // Build rules are generated by the dexpreopt singleton, and here we access build artifacts
+ // via the global boot image config.
+ if a.artApex {
+ for arch, files := range java.DexpreoptedArtApexJars(ctx) {
+ dirInApex := filepath.Join("javalib", arch.String())
+ for _, f := range files {
+ localModule := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
+ filesInfo = append(filesInfo, apexFile{f, localModule, dirInApex, etc, nil, nil})
+ }
+ }
+ }
+
if a.private_key_file == nil {
ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key))
return
@@ -1875,9 +1889,10 @@
return module
}
-func ApexBundleFactory(testApex bool) android.Module {
+func ApexBundleFactory(testApex bool, artApex bool) android.Module {
bundle := newApexBundle()
bundle.testApex = testApex
+ bundle.artApex = artApex
return bundle
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ac5c6fc..614164d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2513,6 +2513,7 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
+ jni_libs: ["libjni"],
}
android_app {
@@ -2522,6 +2523,13 @@
system_modules: "none",
privileged: true,
}
+
+ cc_library_shared {
+ name: "libjni",
+ srcs: ["mylib.cpp"],
+ stl: "none",
+ system_shared_libs: [],
+ }
`)
module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
@@ -2530,6 +2538,7 @@
ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
+ ensureContains(t, copyCmds, "image.apex/lib64/libjni.so")
}
func TestApexWithAppImports(t *testing.T) {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 91a3c99..ff181d8 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -327,14 +327,15 @@
filepath.Dir(fuzz.config.String())+":config.json")
}
- if len(fuzzFiles) > 0 {
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(fuzzFiles, " "))
- })
- }
-
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
fmt.Fprintln(w, "LOCAL_IS_FUZZ_TARGET := true")
+ if len(fuzzFiles) > 0 {
+ fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(fuzzFiles, " "))
+ }
+ if fuzz.installedSharedDeps != nil {
+ fmt.Fprintln(w, "LOCAL_FUZZ_INSTALLED_SHARED_DEPS :="+
+ strings.Join(fuzz.installedSharedDeps, " "))
+ }
})
}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index b42074b..030a076 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -139,9 +139,7 @@
"-Wimplicit-fallthrough",
// Enable clang's thread-safety annotations in libcxx.
- // Turn off -Wthread-safety-negative, to avoid breaking projects that use -Weverything.
"-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
- "-Wno-thread-safety-negative",
// libc++'s math.h has an #include_next outside of system_headers.
"-Wno-gnu-include-next",
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 577fa70..1f06fb0 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -17,10 +17,9 @@
import (
"encoding/json"
"path/filepath"
+ "sort"
"strings"
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
"android/soong/cc/config"
)
@@ -82,6 +81,7 @@
corpus android.Paths
corpusIntermediateDir android.Path
config android.Path
+ installedSharedDeps []string
}
func (fuzz *fuzzBinary) linkerProps() []interface{} {
@@ -91,21 +91,6 @@
}
func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) {
- // Add ../lib[64] to rpath so that out/host/linux-x86/fuzz/<fuzzer> can
- // find out/host/linux-x86/lib[64]/library.so
- runpaths := []string{"../lib"}
- for _, runpath := range runpaths {
- if ctx.toolchain().Is64Bit() {
- runpath += "64"
- }
- fuzz.binaryDecorator.baseLinker.dynamicProperties.RunPaths = append(
- fuzz.binaryDecorator.baseLinker.dynamicProperties.RunPaths, runpath)
- }
-
- // add "" to rpath so that fuzzer binaries can find libraries in their own fuzz directory
- fuzz.binaryDecorator.baseLinker.dynamicProperties.RunPaths = append(
- fuzz.binaryDecorator.baseLinker.dynamicProperties.RunPaths, "")
-
fuzz.binaryDecorator.linkerInit(ctx)
}
@@ -118,9 +103,80 @@
func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
+ // RunPaths on devices isn't instantiated by the base linker.
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
return flags
}
+// This function performs a breadth-first search over the provided module's
+// dependencies using `visitDirectDeps` to enumerate all shared library
+// dependencies. We require breadth-first expansion, as otherwise we may
+// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
+// from a dependency. This may cause issues when dependencies have explicit
+// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
+func collectAllSharedDependencies(
+ module android.Module,
+ sharedDeps map[string]android.Path,
+ ctx android.SingletonContext) {
+ var fringe []android.Module
+
+ // Enumerate the first level of dependencies, as we discard all non-library
+ // modules in the BFS loop below.
+ ctx.VisitDirectDeps(module, func(dep android.Module) {
+ fringe = append(fringe, dep)
+ })
+
+ for i := 0; i < len(fringe); i++ {
+ module := fringe[i]
+ if !isValidSharedDependency(module, sharedDeps) {
+ continue
+ }
+
+ ccModule := module.(*Module)
+ sharedDeps[ccModule.Name()] = ccModule.UnstrippedOutputFile()
+ ctx.VisitDirectDeps(module, func(dep android.Module) {
+ fringe = append(fringe, dep)
+ })
+ }
+}
+
+// This function takes a module and determines if it is a unique shared library
+// that should be installed in the fuzz target output directories. This function
+// returns true, unless:
+// - The module already exists in `sharedDeps`, or
+// - The module is not a shared library, or
+// - The module is a header, stub, or vendor-linked library.
+func isValidSharedDependency(
+ dependency android.Module,
+ sharedDeps map[string]android.Path) bool {
+ // TODO(b/144090547): We should be parsing these modules using
+ // ModuleDependencyTag instead of the current brute-force checking.
+
+ if linkable, ok := dependency.(LinkableInterface); !ok || // Discard non-linkables.
+ !linkable.CcLibraryInterface() || !linkable.Shared() || // Discard static libs.
+ linkable.UseVndk() || // Discard vendor linked libraries.
+ !linkable.CcLibrary() || linkable.BuildStubs() { // Discard stubs libs (only CCLibrary variants).
+ return false
+ }
+
+ // If this library has already been traversed, we don't need to do any more work.
+ if _, exists := sharedDeps[dependency.Name()]; exists {
+ return false
+ }
+ return true
+}
+
+func sharedLibraryInstallLocation(
+ libraryPath android.Path, isHost bool, archString string) string {
+ installLocation := "$(PRODUCT_OUT)/data"
+ if isHost {
+ installLocation = "$(HOST_OUT)"
+ }
+ installLocation = filepath.Join(
+ installLocation, "fuzz", archString, "lib", libraryPath.Base())
+ return installLocation
+}
+
func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
@@ -160,6 +216,22 @@
})
fuzz.config = configPath
}
+
+ // Grab the list of required shared libraries.
+ sharedLibraries := make(map[string]android.Path)
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if isValidSharedDependency(child, sharedLibraries) {
+ sharedLibraries[child.Name()] = child.(*Module).UnstrippedOutputFile()
+ return true
+ }
+ return false
+ })
+
+ for _, lib := range sharedLibraries {
+ fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+ sharedLibraryInstallLocation(
+ lib, ctx.Host(), ctx.Arch().ArchType.String()))
+ }
}
func NewFuzz(hod android.HostOrDeviceSupported) *Module {
@@ -193,28 +265,15 @@
ctx.AppendProperties(&disableDarwinAndLinuxBionic)
})
- // Statically link the STL. This allows fuzz target deployment to not have to
- // include the STL.
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- staticStlLinkage := struct {
- Target struct {
- Linux_glibc struct {
- Stl *string
- }
- }
- }{}
-
- staticStlLinkage.Target.Linux_glibc.Stl = proptools.StringPtr("libc++_static")
- ctx.AppendProperties(&staticStlLinkage)
- })
-
return module
}
// Responsible for generating GNU Make rules that package fuzz targets into
// their architecture & target/host specific zip file.
type fuzzPackager struct {
- packages android.Paths
+ packages android.Paths
+ sharedLibInstallStrings []string
+ fuzzTargets map[string]bool
}
func fuzzPackagingFactory() android.Singleton {
@@ -226,18 +285,31 @@
DestinationPathPrefix string
}
+type archAndLibraryKey struct {
+ ArchDir android.OutputPath
+ Library android.Path
+}
+
func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
// Map between each architecture + host/device combination, and the files that
// need to be packaged (in the tuple of {source file, destination folder in
// archive}).
archDirs := make(map[android.OutputPath][]fileToZip)
+ // List of shared library dependencies for each architecture + host/device combo.
+ archSharedLibraryDeps := make(map[archAndLibraryKey]bool)
+
+ // List of individual fuzz targets, so that 'make fuzz' also installs the targets
+ // to the correct output directories as well.
+ s.fuzzTargets = make(map[string]bool)
+
ctx.VisitAllModules(func(module android.Module) {
// Discard non-fuzz targets.
ccModule, ok := module.(*Module)
if !ok {
return
}
+
fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
if !ok {
return
@@ -249,6 +321,8 @@
return
}
+ s.fuzzTargets[module.Name()] = true
+
hostOrTargetString := "target"
if ccModule.Host() {
hostOrTargetString = "host"
@@ -257,6 +331,29 @@
archString := ccModule.Arch().ArchType.String()
archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+ // Grab the list of required shared libraries.
+ sharedLibraries := make(map[string]android.Path)
+ collectAllSharedDependencies(module, sharedLibraries, ctx)
+
+ for _, library := range sharedLibraries {
+ if _, exists := archSharedLibraryDeps[archAndLibraryKey{archDir, library}]; exists {
+ continue
+ }
+
+ // For each architecture-specific shared library dependency, we need to
+ // install it to the output directory. Setup the install destination here,
+ // which will be used by $(copy-many-files) in the Make backend.
+ archSharedLibraryDeps[archAndLibraryKey{archDir, library}] = true
+ installDestination := sharedLibraryInstallLocation(
+ library, ccModule.Host(), archString)
+ // Escape all the variables, as the install destination here will be called
+ // via. $(eval) in Make.
+ installDestination = strings.ReplaceAll(
+ installDestination, "$", "$$")
+ s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
+ library.String()+":"+installDestination)
+ }
+
// The executable.
archDirs[archDir] = append(archDirs[archDir],
fileToZip{ccModule.UnstrippedOutputFile(), ccModule.Name()})
@@ -280,6 +377,12 @@
}
})
+ // Add the shared library deps for packaging.
+ for key, _ := range archSharedLibraryDeps {
+ archDirs[key.ArchDir] = append(archDirs[key.ArchDir],
+ fileToZip{key.Library, "lib"})
+ }
+
for archDir, filesToZip := range archDirs {
arch := archDir.Base()
hostOrTarget := filepath.Base(filepath.Dir(archDir.String()))
@@ -302,9 +405,22 @@
}
func (s *fuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+ packages := s.packages.Strings()
+ sort.Strings(packages)
+ sort.Strings(s.sharedLibInstallStrings)
// TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
// ready to handle phony targets created in Soong. In the meantime, this
// exports the phony 'fuzz' target and dependencies on packages to
// core/main.mk so that we can use dist-for-goals.
- ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(s.packages.Strings(), " "))
+ ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
+ ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+ strings.Join(s.sharedLibInstallStrings, " "))
+
+ // Preallocate the slice of fuzz targets to minimise memory allocations.
+ fuzzTargets := make([]string, 0, len(s.fuzzTargets))
+ for target, _ := range s.fuzzTargets {
+ fuzzTargets = append(fuzzTargets, target)
+ }
+ sort.Strings(fuzzTargets)
+ ctx.Strict("ALL_FUZZ_TARGETS", strings.Join(fuzzTargets, " "))
}
diff --git a/java/aar.go b/java/aar.go
index afe860c..d8db192 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -520,7 +520,7 @@
}
func (a *AARImport) sdkVersion() string {
- return proptools.StringDefault(a.properties.Sdk_version, defaultSdkVersion(a))
+ return String(a.properties.Sdk_version)
}
func (a *AARImport) systemModules() string {
diff --git a/java/app.go b/java/app.go
index de12b73..d53d626 100644
--- a/java/app.go
+++ b/java/app.go
@@ -205,6 +205,7 @@
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.checkPlatformAPI(ctx)
+ a.checkSdkVersion(ctx)
a.generateAndroidBuildActions(ctx)
}
diff --git a/java/app_test.go b/java/app_test.go
index 5b6ed54..7635f3d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -666,6 +666,44 @@
}
}
+func TestAppSdkVersionByPartition(t *testing.T) {
+ testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ vendor: true,
+ platform_apis: true,
+ }
+ `)
+
+ testJava(t, `
+ android_app {
+ name: "bar",
+ srcs: ["b.java"],
+ platform_apis: true,
+ }
+ `)
+
+ for _, enforce := range []bool{true, false} {
+
+ config := testConfig(nil)
+ config.TestProductVariables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce)
+ bp := `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ product_specific: true,
+ platform_apis: true,
+ }
+ `
+ if enforce {
+ testJavaErrorWithConfig(t, "sdk_version must have a value when the module is located at vendor or product", bp, config)
+ } else {
+ testJavaWithConfig(t, bp, config)
+ }
+ }
+}
+
func TestJNIPackaging(t *testing.T) {
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
diff --git a/java/config/config.go b/java/config/config.go
index 1c55961..333de32 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -87,12 +87,10 @@
return ctx.Config().Getenv("ANDROID_JAVA_HOME")
})
pctx.VariableFunc("JlinkVersion", func(ctx android.PackageVarContext) string {
- switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN") {
- case "false":
- return "9"
- default:
- return "11"
+ if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
+ return override
}
+ return "11"
})
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 74ef667..a29665e 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -51,6 +51,7 @@
type bootImageConfig struct {
name string
+ stem string
modules []string
dexLocations []string
dexPaths android.WritablePaths
@@ -71,7 +72,7 @@
// In addition, each .art file has an associated .oat and .vdex file, and an
// unstripped .oat file
for i, m := range image.modules {
- name := image.name
+ name := image.stem
if i != 0 {
name += "-" + stemOf(m)
}
@@ -139,6 +140,12 @@
return false
}
+func skipDexpreoptArtBootJars(ctx android.BuilderContext) bool {
+ // with EMMA_INSTRUMENT_FRAMEWORK=true ART boot class path libraries have dependencies on framework,
+ // therefore dexpreopt ART libraries cannot be dexpreopted in isolation => no ART boot image
+ return ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
+}
+
type dexpreoptBootJars struct {
defaultBootImage *bootImage
otherImages []*bootImage
@@ -146,6 +153,14 @@
dexpreoptConfigForMake android.WritablePath
}
+// Accessor function for the apex package. Returns nil if dexpreopt is disabled.
+func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.Paths {
+ if skipDexpreoptBootJars(ctx) || skipDexpreoptArtBootJars(ctx) {
+ return nil
+ }
+ return artBootImageConfig(ctx).imagesDeps
+}
+
// dexpreoptBoot singleton rules
func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
if skipDexpreoptBootJars(ctx) {
@@ -169,7 +184,12 @@
// Always create the default boot image first, to get a unique profile rule for all images.
d.defaultBootImage = buildBootImage(ctx, defaultBootImageConfig(ctx))
+ if !skipDexpreoptArtBootJars(ctx) {
+ // Create boot image for the ART apex (build artifacts are accessed via the global boot image config).
+ buildBootImage(ctx, artBootImageConfig(ctx))
+ }
if global.GenerateApexImage {
+ // Create boot images for the JIT-zygote experiment.
d.otherImages = append(d.otherImages, buildBootImage(ctx, apexBootImageConfig(ctx)))
}
@@ -178,8 +198,6 @@
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns a *bootImage.
func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootImage {
- global := dexpreoptGlobalConfig(ctx)
-
image := newBootImage(ctx, config)
bootDexJars := make(android.Paths, len(image.modules))
@@ -223,12 +241,9 @@
bootFrameworkProfileRule(ctx, image, missingDeps)
var allFiles android.Paths
-
- if !global.DisablePreopt {
- for _, target := range image.targets {
- files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
- allFiles = append(allFiles, files.Paths()...)
- }
+ for _, target := range image.targets {
+ files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+ allFiles = append(allFiles, files.Paths()...)
}
if image.zip != nil {
@@ -251,7 +266,7 @@
global := dexpreoptGlobalConfig(ctx)
symbolsDir := image.symbolsDir.Join(ctx, "system/framework", arch.String())
- symbolsFile := symbolsDir.Join(ctx, image.name+".oat")
+ symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
outputDir := image.dir.Join(ctx, "system/framework", arch.String())
outputPath := image.images[arch]
oatLocation := pathtools.ReplaceExtension(dexpreopt.PathToLocation(outputPath, arch), "oat")
@@ -381,8 +396,9 @@
if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
return nil
}
- return ctx.Config().Once(bootImageProfileRuleKey, func() interface{} {
+ profile := ctx.Config().Once(bootImageProfileRuleKey, func() interface{} {
tools := global.Tools
+ defaultProfile := "frameworks/base/config/boot-image-profile.txt"
rule := android.NewRuleBuilder()
rule.MissingDeps(missingDeps)
@@ -394,18 +410,13 @@
bootImageProfile = combinedBootImageProfile
} else if len(global.BootImageProfiles) == 1 {
bootImageProfile = global.BootImageProfiles[0]
+ } else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() {
+ bootImageProfile = path.Path()
} else {
- // If not set, use the default. Some branches like master-art-host don't have frameworks/base, so manually
- // handle the case that the default is missing. Those branches won't attempt to build the profile rule,
- // and if they do they'll get a missing deps error.
- defaultProfile := "frameworks/base/config/boot-image-profile.txt"
- path := android.ExistentPathForSource(ctx, defaultProfile)
- if path.Valid() {
- bootImageProfile = path.Path()
- } else {
- missingDeps = append(missingDeps, defaultProfile)
- bootImageProfile = android.PathForOutput(ctx, "missing")
- }
+ // No profile (not even a default one, which is the case on some branches
+ // like master-art-host that don't have frameworks/base).
+ // Return nil and continue without profile.
+ return nil
}
profile := image.dir.Join(ctx, "boot.prof")
@@ -425,7 +436,11 @@
image.profileInstalls = rule.Installs()
return profile
- }).(android.WritablePath)
+ })
+ if profile == nil {
+ return nil // wrap nil into a typed pointer with value nil
+ }
+ return profile.(android.WritablePath)
}
var bootImageProfileRuleKey = android.NewOnceKey("bootImageProfileRule")
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 244bd52..a684ab2 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -62,7 +62,6 @@
bootArt := dexpreoptBootJars.Output("boot.art")
expectedInputs := []string{
- "dex_bootjars/boot.prof",
"dex_bootjars_input/foo.jar",
"dex_bootjars_input/bar.jar",
"dex_bootjars_input/baz.jar",
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index b3b1317..a6661b3 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -106,15 +106,20 @@
return moduleName
}
-func getBootImageConfig(ctx android.PathContext, key android.OnceKey, name string,
- needZip bool) bootImageConfig {
+// Construct a variant of the global config for dexpreopted bootclasspath jars. The variants differ
+// in the list of input jars (libcore, framework, or both), in the naming scheme for the dexpreopt
+// files (ART recognizes "apex" names as special), and whether to include a zip archive.
+//
+// 'name' is a string unique for each profile (used in directory names and ninja rule names)
+// 'stem' is the basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}.
+func getBootImageConfig(ctx android.PathContext, key android.OnceKey, name string, stem string,
+ needZip bool, artApexJarsOnly bool) bootImageConfig {
+
return ctx.Config().Once(key, func() interface{} {
global := dexpreoptGlobalConfig(ctx)
artModules := global.ArtApexJars
- nonFrameworkModules := concat(artModules, global.ProductUpdatableBootModules)
- frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules)
- imageModules := concat(artModules, frameworkModules)
+ imageModules := artModules
var bootLocations []string
@@ -123,9 +128,15 @@
filepath.Join("/apex/com.android.art/javalib", stemOf(m)+".jar"))
}
- for _, m := range frameworkModules {
- bootLocations = append(bootLocations,
- filepath.Join("/system/framework", stemOf(m)+".jar"))
+ if !artApexJarsOnly {
+ nonFrameworkModules := concat(artModules, global.ProductUpdatableBootModules)
+ frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules)
+ imageModules = concat(imageModules, frameworkModules)
+
+ for _, m := range frameworkModules {
+ bootLocations = append(bootLocations,
+ filepath.Join("/system/framework", stemOf(m)+".jar"))
+ }
}
// The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before
@@ -143,13 +154,14 @@
var zip android.WritablePath
if needZip {
- zip = dir.Join(ctx, name+".zip")
+ zip = dir.Join(ctx, stem+".zip")
}
targets := dexpreoptTargets(ctx)
imageConfig := bootImageConfig{
name: name,
+ stem: stem,
modules: imageModules,
dexLocations: bootLocations,
dexPaths: bootDexPaths,
@@ -163,7 +175,7 @@
for _, target := range targets {
imageDir := dir.Join(ctx, "system/framework", target.Arch.ArchType.String())
- imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, name+".art")
+ imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, stem+".art")
imagesDeps := make([]android.Path, 0, len(imageConfig.modules)*3)
for _, dep := range imageConfig.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex") {
@@ -176,15 +188,25 @@
}).(bootImageConfig)
}
+// Default config is the one that goes in the system image. It includes both libcore and framework.
var defaultBootImageConfigKey = android.NewOnceKey("defaultBootImageConfig")
-var apexBootImageConfigKey = android.NewOnceKey("apexBootImageConfig")
func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
- return getBootImageConfig(ctx, defaultBootImageConfigKey, "boot", true)
+ return getBootImageConfig(ctx, defaultBootImageConfigKey, "boot", "boot", true, false)
}
+// Apex config is used for the JIT-zygote experiment. It includes both libcore and framework, but AOT-compiles only libcore.
+var apexBootImageConfigKey = android.NewOnceKey("apexBootImageConfig")
+
func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
- return getBootImageConfig(ctx, apexBootImageConfigKey, "apex", false)
+ return getBootImageConfig(ctx, apexBootImageConfigKey, "apex", "apex", false, false)
+}
+
+// ART config is the one used for the ART apex. It includes only libcore.
+var artBootImageConfigKey = android.NewOnceKey("artBootImageConfig")
+
+func artBootImageConfig(ctx android.PathContext) bootImageConfig {
+ return getBootImageConfig(ctx, artBootImageConfigKey, "art", "boot", false, true)
}
func defaultBootclasspath(ctx android.PathContext) []string {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 5d01b54..54f93fe 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -404,7 +404,7 @@
var _ android.OutputFileProducer = (*Javadoc)(nil)
func (j *Javadoc) sdkVersion() string {
- return proptools.StringDefault(j.properties.Sdk_version, defaultSdkVersion(j))
+ return String(j.properties.Sdk_version)
}
func (j *Javadoc) systemModules() string {
@@ -1325,13 +1325,8 @@
validatingNullability :=
strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs") ||
String(d.properties.Validate_nullability_from_list) != ""
+
migratingNullability := String(d.properties.Previous_api) != ""
-
- if !(migratingNullability || validatingNullability) {
- ctx.PropertyErrorf("previous_api",
- "has to be non-empty if annotations was enabled (unless validating nullability)")
- }
-
if migratingNullability {
previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
cmd.FlagWithInput("--migrate-nullness ", previousApi)
diff --git a/java/java.go b/java/java.go
index 88f5d87..9bbdff7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -54,6 +54,18 @@
android.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}
+func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
+ if j.SocSpecific() || j.DeviceSpecific() ||
+ (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
+ if sc, ok := ctx.Module().(sdkContext); ok {
+ if sc.sdkVersion() == "" {
+ ctx.PropertyErrorf("sdk_version",
+ "sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).")
+ }
+ }
+ }
+}
+
func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
if sc, ok := ctx.Module().(sdkContext); ok {
usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
@@ -430,6 +442,11 @@
target android.Target
}
+func IsJniDepTag(depTag blueprint.DependencyTag) bool {
+ _, ok := depTag.(*jniDependencyTag)
+ return ok
+}
+
var (
staticLibTag = dependencyTag{name: "staticlib"}
libTag = dependencyTag{name: "javalib"}
@@ -447,18 +464,6 @@
usesLibTag = dependencyTag{name: "uses-library"}
)
-func defaultSdkVersion(ctx checkVendorModuleContext) string {
- if ctx.SocSpecific() || ctx.DeviceSpecific() {
- return "system_current"
- }
- return ""
-}
-
-type checkVendorModuleContext interface {
- SocSpecific() bool
- DeviceSpecific() bool
-}
-
type sdkDep struct {
useModule, useFiles, useDefaultLibs, invalidVersion bool
@@ -505,7 +510,7 @@
}
func (j *Module) sdkVersion() string {
- return proptools.StringDefault(j.deviceProperties.Sdk_version, defaultSdkVersion(j))
+ return String(j.deviceProperties.Sdk_version)
}
func (j *Module) systemModules() string {
@@ -1636,6 +1641,7 @@
}
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.checkSdkVersion(ctx)
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
j.dexpreopter.isInstallable = Bool(j.properties.Installable)
@@ -1979,7 +1985,7 @@
}
func (j *Import) sdkVersion() string {
- return proptools.StringDefault(j.properties.Sdk_version, defaultSdkVersion(j))
+ return String(j.properties.Sdk_version)
}
func (j *Import) minSdkVersion() string {
diff --git a/java/java_test.go b/java/java_test.go
index a6ae503..e7b68dd 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -23,6 +23,8 @@
"strings"
"testing"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
@@ -228,9 +230,13 @@
android.FailIfErrored(t, errs)
}
-func testJavaError(t *testing.T, pattern string, bp string) {
+func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) {
t.Helper()
- config := testConfig(nil)
+ return testJavaErrorWithConfig(t, pattern, bp, testConfig(nil))
+}
+
+func testJavaErrorWithConfig(t *testing.T, pattern string, bp string, config android.Config) (*android.TestContext, android.Config) {
+ t.Helper()
ctx := testContext(bp, nil)
pathCtx := android.PathContextForTesting(config, nil)
@@ -240,20 +246,26 @@
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs)
- return
+ return ctx, config
}
_, errs = ctx.PrepareBuildActions(config)
if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs)
- return
+ return ctx, config
}
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+
+ return ctx, config
}
func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
t.Helper()
- config := testConfig(nil)
+ return testJavaWithConfig(t, bp, testConfig(nil))
+}
+
+func testJavaWithConfig(t *testing.T, bp string, config android.Config) (*android.TestContext, android.Config) {
+ t.Helper()
ctx := testContext(bp, nil)
run(t, ctx, config)
@@ -315,29 +327,38 @@
}
}
-func TestSdkVersion(t *testing.T) {
- ctx, _ := testJava(t, `
+func TestSdkVersionByPartition(t *testing.T) {
+ testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
java_library {
name: "foo",
srcs: ["a.java"],
vendor: true,
}
+ `)
+ testJava(t, `
java_library {
name: "bar",
srcs: ["b.java"],
}
`)
- foo := ctx.ModuleForTests("foo", "android_common").Module().(*Library)
- bar := ctx.ModuleForTests("bar", "android_common").Module().(*Library)
+ for _, enforce := range []bool{true, false} {
- if foo.sdkVersion() != "system_current" {
- t.Errorf("If sdk version of vendor module is empty, it must change to system_current.")
- }
-
- if bar.sdkVersion() != "" {
- t.Errorf("If sdk version of non-vendor module is empty, it keeps empty.")
+ config := testConfig(nil)
+ config.TestProductVariables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce)
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ product_specific: true,
+ }
+ `
+ if enforce {
+ testJavaErrorWithConfig(t, "sdk_version must have a value when the module is located at vendor or product", bp, config)
+ } else {
+ testJavaWithConfig(t, bp, config)
+ }
}
}
diff --git a/ui/build/config.go b/ui/build/config.go
index 686ca3e..92aee4d 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -219,8 +219,8 @@
if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
return override
}
- if toolchain9, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain9 == "false" {
- return java9Home
+ if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
+ ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
}
return java11Home
}()