summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Android.bp2
-rw-r--r--java/aar.go22
-rw-r--r--java/androidmk.go16
-rwxr-xr-xjava/app.go94
-rw-r--r--java/app_import.go11
-rw-r--r--java/app_import_test.go149
-rw-r--r--java/app_test.go132
-rw-r--r--java/base.go50
-rw-r--r--java/builder.go135
-rw-r--r--java/config/config.go51
-rw-r--r--java/config/error_prone.go24
-rw-r--r--java/config/kotlin.go6
-rw-r--r--java/dex.go11
-rw-r--r--java/dex_test.go103
-rw-r--r--java/droidstubs.go12
-rw-r--r--java/hiddenapi_modular.go62
-rw-r--r--java/java.go209
-rw-r--r--java/java_test.go2
-rw-r--r--java/jdeps.go2
-rw-r--r--java/kotlin.go63
-rw-r--r--java/kotlin_test.go78
-rw-r--r--java/lint.go22
-rw-r--r--java/plugin.go29
-rw-r--r--java/sdk_library.go8
-rw-r--r--java/testing.go4
25 files changed, 845 insertions, 452 deletions
diff --git a/java/Android.bp b/java/Android.bp
index c0629414e..df0d1eb3d 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -15,6 +15,7 @@ bootstrap_go_package {
"soong-dexpreopt",
"soong-genrule",
"soong-java-config",
+ "soong-provenance",
"soong-python",
"soong-remoteexec",
"soong-tradefed",
@@ -81,6 +82,7 @@ bootstrap_go_package {
"app_test.go",
"bootclasspath_fragment_test.go",
"device_host_converter_test.go",
+ "dex_test.go",
"dexpreopt_test.go",
"dexpreopt_bootjars_test.go",
"droiddoc_test.go",
diff --git a/java/aar.go b/java/aar.go
index 8e1025361..00ff7e774 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -598,16 +598,26 @@ func AndroidLibraryFactory() android.Module {
// AAR (android library) prebuilts
//
+// Properties for android_library_import
type AARImportProperties struct {
+ // ARR (android library prebuilt) filepath. Exactly one ARR is required.
Aars []string `android:"path"`
-
- Sdk_version *string
+ // If not blank, set to the version of the sdk to compile against.
+ // Defaults to private.
+ // Values are of one of the following forms:
+ // 1) numerical API level, "current", "none", or "core_platform"
+ // 2) An SDK kind with an API level: "<sdk kind>_<API level>"
+ // See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds.
+ // If the SDK kind is empty, it will be set to public
+ Sdk_version *string
+ // If not blank, set the minimum version of the sdk that the compiled artifacts will run against.
+ // Defaults to sdk_version if not set. See sdk_version for possible values.
Min_sdk_version *string
-
+ // List of java static libraries that the included ARR (android library prebuilts) has dependencies to.
Static_libs []string
- Libs []string
-
- // if set to true, run Jetifier against .aar file. Defaults to false.
+ // List of java libraries that the included ARR (android library prebuilts) has dependencies to.
+ Libs []string
+ // If set to true, run Jetifier against .aar file. Defaults to false.
Jetifier *bool
}
diff --git a/java/androidmk.go b/java/androidmk.go
index b930441f3..80b828d45 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -409,22 +409,6 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
},
},
- ExtraFooters: []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- if app.noticeOutputs.Merged.Valid() {
- fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
- app.installApkName, app.noticeOutputs.Merged.String(), app.installApkName+"_NOTICE")
- }
- if app.noticeOutputs.TxtOutput.Valid() {
- fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
- app.installApkName, app.noticeOutputs.TxtOutput.String(), app.installApkName+"_NOTICE.txt")
- }
- if app.noticeOutputs.HtmlOutput.Valid() {
- fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
- app.installApkName, app.noticeOutputs.HtmlOutput.String(), app.installApkName+"_NOTICE.html")
- }
- },
- },
}}
}
diff --git a/java/app.go b/java/app.go
index 96fd61ad9..2b52eab15 100755
--- a/java/app.go
+++ b/java/app.go
@@ -19,7 +19,6 @@ package java
import (
"path/filepath"
- "sort"
"strings"
"github.com/google/blueprint"
@@ -164,8 +163,6 @@ type AndroidApp struct {
additionalAaptFlags []string
- noticeOutputs android.NoticeOutputs
-
overriddenManifestPackageName string
android.ApexBundleDepsInfo
@@ -523,53 +520,6 @@ func (a *AndroidApp) JNISymbolsInstalls(installPath string) android.RuleBuilderI
return jniSymbols
}
-func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext) {
- // Collect NOTICE files from all dependencies.
- seenModules := make(map[android.Module]bool)
- noticePathSet := make(map[android.Path]bool)
-
- ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
- // Have we already seen this?
- if _, ok := seenModules[child]; ok {
- return false
- }
- seenModules[child] = true
-
- // Skip host modules.
- if child.Target().Os.Class == android.Host {
- return false
- }
-
- paths := child.(android.Module).NoticeFiles()
- if len(paths) > 0 {
- for _, path := range paths {
- noticePathSet[path] = true
- }
- }
- return true
- })
-
- // If the app has one, add it too.
- if len(a.NoticeFiles()) > 0 {
- for _, path := range a.NoticeFiles() {
- noticePathSet[path] = true
- }
- }
-
- if len(noticePathSet) == 0 {
- return
- }
- var noticePaths []android.Path
- for path := range noticePathSet {
- noticePaths = append(noticePaths, path)
- }
- sort.Slice(noticePaths, func(i, j int) bool {
- return noticePaths[i].String() < noticePaths[j].String()
- })
-
- a.noticeOutputs = android.BuildNoticeOutput(ctx, a.installDir, a.installApkName+".apk", noticePaths)
-}
-
// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
// isn't a cert module reference. Also checks and enforces system cert restriction if applicable.
func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, ctx android.ModuleContext) []Certificate {
@@ -636,9 +586,16 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
}
a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
- a.noticeBuildActions(ctx)
if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
- a.aapt.noticeFile = a.noticeOutputs.HtmlGzOutput
+ noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz")
+ android.BuildNoticeHtmlOutputFromLicenseMetadata(ctx, noticeFile)
+ noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Text("cp").
+ Input(noticeFile).
+ Output(noticeAssetPath)
+ builder.Build("notice_dir", "Building notice dir")
+ a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath)
}
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
@@ -681,7 +638,21 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
}
certificates := processMainCert(a.ModuleBase, a.getCertString(ctx), certificateDeps, ctx)
- a.certificate = certificates[0]
+
+ // This can be reached with an empty certificate list if AllowMissingDependencies is set
+ // and the certificate property for this module is a module reference to a missing module.
+ if len(certificates) > 0 {
+ a.certificate = certificates[0]
+ } else {
+ if !ctx.Config().AllowMissingDependencies() && len(ctx.GetMissingDependencies()) > 0 {
+ panic("Should only get here if AllowMissingDependencies set and there are missing dependencies")
+ }
+ // Set a certificate to avoid panics later when accessing it.
+ a.certificate = Certificate{
+ Key: android.PathForModuleOut(ctx, "missing.pk8"),
+ Pem: android.PathForModuleOut(ctx, "missing.pem"),
+ }
+ }
// Build a final signed app package.
packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk")
@@ -1450,7 +1421,8 @@ func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *An
}
type bazelAndroidAppAttributes struct {
- *javaLibraryAttributes
+ *javaCommonAttributes
+ Deps bazel.LabelListAttribute
Manifest bazel.Label
Custom_package *string
Resource_files bazel.LabelListAttribute
@@ -1460,7 +1432,16 @@ type bazelAndroidAppAttributes struct {
// ConvertWithBp2build is used to convert android_app to Bazel.
func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- libAttrs := a.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx)
+
+ deps := depLabels.Deps
+ if !commonAttrs.Srcs.IsEmpty() {
+ deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
+ } else if !deps.IsEmpty() || !depLabels.StaticDeps.IsEmpty() {
+ ctx.ModuleErrorf("android_app has dynamic or static dependencies but no sources." +
+ " Bazel does not allow direct dependencies without sources nor exported" +
+ " dependencies on android_binary rule.")
+ }
manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
@@ -1483,7 +1464,8 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
}
attrs := &bazelAndroidAppAttributes{
- libAttrs,
+ commonAttrs,
+ deps,
android.BazelLabelForModuleSrcSingle(ctx, manifest),
// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
a.overridableAppProperties.Package_name,
diff --git a/java/app_import.go b/java/app_import.go
index 3e5f972a4..b017eca60 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -22,6 +22,7 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/provenance"
)
func init() {
@@ -57,6 +58,8 @@ type AndroidAppImport struct {
installPath android.InstallPath
hideApexVariantFromMake bool
+
+ provenanceMetaDataFile android.OutputPath
}
type AndroidAppImportProperties struct {
@@ -343,6 +346,8 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
+ artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
+ a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
// TODO: androidmk converter jni libs
@@ -368,6 +373,10 @@ func (a *AndroidAppImport) Certificate() Certificate {
return a.certificate
}
+func (a *AndroidAppImport) ProvenanceMetaDataFile() android.OutputPath {
+ return a.provenanceMetaDataFile
+}
+
var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
@@ -457,7 +466,7 @@ func createVariantGroupType(variants []string, variantGroupName string) reflect.
// apk: "prebuilts/example_xhdpi.apk",
// },
// },
-// certificate: "PRESIGNED",
+// presigned: true,
// }
func AndroidAppImportFactory() android.Module {
module := &AndroidAppImport{}
diff --git a/java/app_import_test.go b/java/app_import_test.go
index efa52c178..8f6c75fa9 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -53,6 +53,11 @@ func TestAndroidAppImport(t *testing.T) {
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
@@ -74,6 +79,12 @@ func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
t.Errorf("dexpreopt shouldn't have run.")
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_Presigned(t *testing.T) {
@@ -102,6 +113,12 @@ func TestAndroidAppImport_Presigned(t *testing.T) {
if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
t.Errorf("can't find aligning rule")
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_SigningLineage(t *testing.T) {
@@ -137,6 +154,12 @@ func TestAndroidAppImport_SigningLineage(t *testing.T) {
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
@@ -163,6 +186,12 @@ func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
@@ -192,6 +221,12 @@ func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_DpiVariants(t *testing.T) {
@@ -214,40 +249,46 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) {
}
`
testCases := []struct {
- name string
- aaptPreferredConfig *string
- aaptPrebuiltDPI []string
- expected string
+ name string
+ aaptPreferredConfig *string
+ aaptPrebuiltDPI []string
+ expected string
+ expectedProvenanceMetaDataArtifactPath string
}{
{
- name: "no preferred",
- aaptPreferredConfig: nil,
- aaptPrebuiltDPI: []string{},
- expected: "verify_uses_libraries/apk/app.apk",
+ name: "no preferred",
+ aaptPreferredConfig: nil,
+ aaptPrebuiltDPI: []string{},
+ expected: "verify_uses_libraries/apk/app.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
},
{
- name: "AAPTPreferredConfig matches",
- aaptPreferredConfig: proptools.StringPtr("xhdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
- expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ name: "AAPTPreferredConfig matches",
+ aaptPreferredConfig: proptools.StringPtr("xhdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
},
{
- name: "AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
- expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
+ name: "AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
+ expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xxhdpi.apk",
},
{
- name: "non-first AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
- expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ name: "non-first AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
},
{
- name: "no matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
- expected: "verify_uses_libraries/apk/app.apk",
+ name: "no matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
+ expected: "verify_uses_libraries/apk/app.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
},
}
@@ -270,6 +311,12 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) {
if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
+
+ provenanceMetaDataRule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.expectedProvenanceMetaDataArtifactPath, provenanceMetaDataRule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", provenanceMetaDataRule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", provenanceMetaDataRule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", provenanceMetaDataRule.Args["install_path"])
}
}
@@ -290,16 +337,25 @@ func TestAndroidAppImport_Filename(t *testing.T) {
`)
testCases := []struct {
- name string
- expected string
+ name string
+ expected string
+ onDevice string
+ expectedArtifactPath string
+ expectedMetaDataPath string
}{
{
- name: "foo",
- expected: "foo.apk",
+ name: "foo",
+ expected: "foo.apk",
+ onDevice: "/system/app/foo/foo.apk",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto",
},
{
- name: "bar",
- expected: "bar_sample.apk",
+ name: "bar",
+ expected: "bar_sample.apk",
+ onDevice: "/system/app/bar/bar_sample.apk",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto",
},
}
@@ -316,15 +372,23 @@ func TestAndroidAppImport_Filename(t *testing.T) {
t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
actualValues, expectedValues)
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.expectedArtifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", test.expectedMetaDataPath, rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", test.name, rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.onDevice, rule.Args["install_path"])
}
}
func TestAndroidAppImport_ArchVariants(t *testing.T) {
// The test config's target arch is ARM64.
testCases := []struct {
- name string
- bp string
- expected string
+ name string
+ bp string
+ expected string
+ artifactPath string
+ metaDataPath string
+ installPath string
}{
{
name: "matching arch",
@@ -343,7 +407,9 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
},
}
`,
- expected: "verify_uses_libraries/apk/app_arm64.apk",
+ expected: "verify_uses_libraries/apk/app_arm64.apk",
+ artifactPath: "prebuilts/apk/app_arm64.apk",
+ installPath: "/system/app/foo/foo.apk",
},
{
name: "no matching arch",
@@ -362,7 +428,9 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
},
}
`,
- expected: "verify_uses_libraries/apk/app.apk",
+ expected: "verify_uses_libraries/apk/app.apk",
+ artifactPath: "prebuilts/apk/app.apk",
+ installPath: "/system/app/foo/foo.apk",
},
{
name: "no matching arch without default",
@@ -380,7 +448,9 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
},
}
`,
- expected: "",
+ expected: "",
+ artifactPath: "prebuilts/apk/app_arm.apk",
+ installPath: "/system/app/foo/foo.apk",
},
}
@@ -393,6 +463,8 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
if variant.Module().Enabled() {
t.Error("module should have been disabled, but wasn't")
}
+ rule := variant.MaybeRule("genProvenanceMetaData")
+ android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
continue
}
jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
@@ -403,6 +475,11 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
}
}
diff --git a/java/app_test.go b/java/app_test.go
index 16bbec158..6a4508cd6 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -27,7 +27,6 @@ import (
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
- "android/soong/genrule"
)
// testApp runs tests using the prepareForJavaTest
@@ -2722,116 +2721,6 @@ func TestCodelessApp(t *testing.T) {
}
}
-func TestEmbedNotice(t *testing.T) {
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- cc.PrepareForTestWithCcDefaultModules,
- genrule.PrepareForTestWithGenRuleBuildComponents,
- android.MockFS{
- "APP_NOTICE": nil,
- "GENRULE_NOTICE": nil,
- "LIB_NOTICE": nil,
- "TOOL_NOTICE": nil,
- }.AddToFixture(),
- ).RunTestWithBp(t, `
- android_app {
- name: "foo",
- srcs: ["a.java"],
- static_libs: ["javalib"],
- jni_libs: ["libjni"],
- notice: "APP_NOTICE",
- embed_notices: true,
- sdk_version: "current",
- }
-
- // No embed_notice flag
- android_app {
- name: "bar",
- srcs: ["a.java"],
- jni_libs: ["libjni"],
- notice: "APP_NOTICE",
- sdk_version: "current",
- }
-
- // No NOTICE files
- android_app {
- name: "baz",
- srcs: ["a.java"],
- embed_notices: true,
- sdk_version: "current",
- }
-
- cc_library {
- name: "libjni",
- system_shared_libs: [],
- stl: "none",
- notice: "LIB_NOTICE",
- sdk_version: "current",
- }
-
- java_library {
- name: "javalib",
- srcs: [
- ":gen",
- ],
- sdk_version: "current",
- }
-
- genrule {
- name: "gen",
- tools: ["gentool"],
- out: ["gen.java"],
- notice: "GENRULE_NOTICE",
- }
-
- java_binary_host {
- name: "gentool",
- srcs: ["b.java"],
- notice: "TOOL_NOTICE",
- }
- `)
-
- // foo has NOTICE files to process, and embed_notices is true.
- foo := result.ModuleForTests("foo", "android_common")
- // verify merge notices rule.
- mergeNotices := foo.Rule("mergeNoticesRule")
- noticeInputs := mergeNotices.Inputs.Strings()
- // TOOL_NOTICE should be excluded as it's a host module.
- if len(mergeNotices.Inputs) != 3 {
- t.Errorf("number of input notice files: expected = 3, actual = %q", noticeInputs)
- }
- if !inList("APP_NOTICE", noticeInputs) {
- t.Errorf("APP_NOTICE is missing from notice files, %q", noticeInputs)
- }
- if !inList("LIB_NOTICE", noticeInputs) {
- t.Errorf("LIB_NOTICE is missing from notice files, %q", noticeInputs)
- }
- if !inList("GENRULE_NOTICE", noticeInputs) {
- t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
- }
- // aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
- res := foo.Output("package-res.apk")
- aapt2Flags := res.Args["flags"]
- e := "-A out/soong/.intermediates/foo/android_common/NOTICE"
- android.AssertStringDoesContain(t, "expected.apkPath", aapt2Flags, e)
-
- // bar has NOTICE files to process, but embed_notices is not set.
- bar := result.ModuleForTests("bar", "android_common")
- res = bar.Output("package-res.apk")
- aapt2Flags = res.Args["flags"]
- e = "-A out/soong/.intermediates/bar/android_common/NOTICE"
- android.AssertStringDoesNotContain(t, "bar shouldn't have the asset dir flag for NOTICE", aapt2Flags, e)
-
- // baz's embed_notice is true, but it doesn't have any NOTICE files.
- baz := result.ModuleForTests("baz", "android_common")
- res = baz.Output("package-res.apk")
- aapt2Flags = res.Args["flags"]
- e = "-A out/soong/.intermediates/baz/android_common/NOTICE"
- if strings.Contains(aapt2Flags, e) {
- t.Errorf("baz shouldn't have the asset dir flag for NOTICE: %q", e)
- }
-}
-
func TestUncompressDex(t *testing.T) {
testCases := []struct {
name string
@@ -3059,3 +2948,24 @@ func TestTargetSdkVersionManifestFixer(t *testing.T) {
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
}
}
+
+func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ certificate: ":missing_certificate",
+ sdk_version: "current",
+ }`)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ fooApk := foo.Output("foo.apk")
+ if fooApk.Rule != android.ErrorRule {
+ t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
+ }
+ android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
+}
diff --git a/java/base.go b/java/base.go
index 9978a66fc..b925350a0 100644
--- a/java/base.go
+++ b/java/base.go
@@ -185,12 +185,12 @@ type CommonProperties struct {
// constructing a new module.
type DeviceProperties struct {
// If not blank, set to the version of the sdk to compile against.
- // Defaults to compiling against the current platform.
+ // Defaults to private.
// Values are of one of the following forms:
- // 1) numerical API level or "current"
- // 2) An SDK kind with an API level: "<sdk kind>_<API level>". See
- // build/soong/android/sdk_version.go for the complete and up to date list of
- // SDK kinds. If the SDK kind value is empty, it will be set to public.
+ // 1) numerical API level, "current", "none", or "core_platform"
+ // 2) An SDK kind with an API level: "<sdk kind>_<API level>"
+ // See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds.
+ // If the SDK kind is empty, it will be set to public.
Sdk_version *string
// if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
@@ -207,7 +207,7 @@ type DeviceProperties struct {
// Whether to compile against the platform APIs instead of an SDK.
// If true, then sdk_version must be empty. The value of this field
- // is ignored when module's type isn't android_app.
+ // is ignored when module's type isn't android_app, android_test, or android_test_helper_app.
Platform_apis *bool
Aidl struct {
@@ -872,6 +872,7 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB
// classpath
flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...)
flags.classpath = append(flags.classpath, deps.classpath...)
+ flags.dexClasspath = append(flags.dexClasspath, deps.dexClasspath...)
flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...)
flags.processorPath = append(flags.processorPath, deps.processorPath...)
flags.errorProneProcessorPath = append(flags.errorProneProcessorPath, deps.errorProneProcessorPath...)
@@ -1047,12 +1048,24 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
}
+ // We don't currently run annotation processors in turbine, which means we can't use turbine
+ // generated header jars when an annotation processor that generates API is enabled. One
+ // exception (handled further below) is when kotlin sources are enabled, in which case turbine
+ // is used to run all of the annotation processors.
+ disableTurbine := deps.disableTurbine
+
// Collect .java files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
var kotlinJars android.Paths
+ var kotlinHeaderJars android.Paths
if srcFiles.HasExt(".kt") {
+ // When using kotlin sources turbine is used to generate annotation processor sources,
+ // including for annotation processors that generate API, so we can use turbine for
+ // java sources too.
+ disableTurbine = false
+
// user defined kotlin flags.
kotlincFlags := j.properties.Kotlincflags
CheckKotlincFlags(ctx, kotlincFlags)
@@ -1090,6 +1103,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
+ flags.dexClasspath = append(flags.dexClasspath, deps.kotlinAnnotations...)
+
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
@@ -1106,18 +1121,24 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
- kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
+ kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
if ctx.Failed() {
return
}
// Make javac rule depend on the kotlinc rule
- flags.classpath = append(flags.classpath, kotlinJar)
+ flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
kotlinJars = append(kotlinJars, kotlinJar)
+ kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
+
// Jar kotlin classes into the final jar after javac
if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
+ kotlinHeaderJars = append(kotlinHeaderJars, deps.kotlinStdlib...)
+ } else {
+ flags.dexClasspath = append(flags.dexClasspath, deps.kotlinStdlib...)
}
}
@@ -1129,7 +1150,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
enableSharding := false
var headerJarFileWithoutDepsOrJarjar android.Path
- if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
+ if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
enableSharding = true
// Formerly, there was a check here that prevented annotation processors
@@ -1139,7 +1160,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// with sharding enabled. See: b/77284273.
}
headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
- j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
+ j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
if ctx.Failed() {
return
}
@@ -1673,6 +1694,8 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
}
dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...)
+ dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...)
+ dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...)
}
func (j *Module) CompilerDeps() []string {
@@ -1842,6 +1865,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
} else if sdkDep.useFiles {
// sdkDep.jar is actually equivalent to turbine header.jar.
deps.classpath = append(deps.classpath, sdkDep.jars...)
+ deps.dexClasspath = append(deps.dexClasspath, sdkDep.jars...)
deps.aidlPreprocess = sdkDep.aidl
} else {
deps.aidlPreprocess = sdkDep.aidl
@@ -1866,7 +1890,9 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
if dep, ok := module.(SdkLibraryDependency); ok {
switch tag {
case libTag:
- deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
+ depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))
+ deps.classpath = append(deps.classpath, depHeaderJars...)
+ deps.dexClasspath = append(deps.dexClasspath, depHeaderJars...)
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
@@ -1885,6 +1911,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars...)
+ deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
@@ -1952,6 +1979,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case libTag:
checkProducesJars(ctx, dep)
deps.classpath = append(deps.classpath, dep.Srcs()...)
+ deps.dexClasspath = append(deps.classpath, dep.Srcs()...)
case staticLibTag:
checkProducesJars(ctx, dep)
deps.classpath = append(deps.classpath, dep.Srcs()...)
diff --git a/java/builder.go b/java/builder.go
index e64a61f5c..c0fadd42c 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -131,31 +131,28 @@ var (
turbine, turbineRE = pctx.RemoteStaticRules("turbine",
blueprint.RuleParams{
- Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` +
- `--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` +
+ Command: `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} $outputFlags ` +
+ `--sources @$out.rsp --source_jars $srcJars ` +
`--javacopts ${config.CommonJdkFlags} ` +
- `$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` +
- `${config.Ziptime} $out.tmp && ` +
- `(if cmp -s $out.tmp $out ; then rm $out.tmp ; else mv $out.tmp $out ; fi )`,
+ `$javacFlags -source $javaVersion -target $javaVersion -- $turbineFlags && ` +
+ `(for o in $outputs; do if cmp -s $${o}.tmp $${o} ; then rm $${o}.tmp ; else mv $${o}.tmp $${o} ; fi; done )`,
CommandDeps: []string{
"${config.TurbineJar}",
"${config.JavaCmd}",
- "${config.Ziptime}",
},
Rspfile: "$out.rsp",
RspfileContent: "$in",
Restat: true,
},
&remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"},
- ExecStrategy: "${config.RETurbineExecStrategy}",
- Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"},
- RSPFiles: []string{"${out}.rsp"},
- OutputFiles: []string{"$out.tmp"},
- OutputDirectories: []string{"$outDir"},
- ToolchainInputs: []string{"${config.JavaCmd}"},
- Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
- }, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"})
+ ExecStrategy: "${config.RETurbineExecStrategy}",
+ Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"},
+ RSPFiles: []string{"${out}.rsp"},
+ OutputFiles: []string{"$rbeOutputs"},
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ []string{"javacFlags", "turbineFlags", "outputFlags", "javaVersion", "outputs", "rbeOutputs", "srcJars"}, []string{"implicits"})
jar, jarRE = pctx.RemoteStaticRules("jar",
blueprint.RuleParams{
@@ -247,16 +244,33 @@ func init() {
}
type javaBuilderFlags struct {
- javacFlags string
- bootClasspath classpath
- classpath classpath
+ javacFlags string
+
+ // bootClasspath is the list of jars that form the boot classpath (generally the java.* and
+ // android.* classes) for tools that still use it. javac targeting 1.9 or higher uses
+ // systemModules and java9Classpath instead.
+ bootClasspath classpath
+
+ // classpath is the list of jars that form the classpath for javac and kotlinc rules. It
+ // contains header jars for all static and non-static dependencies.
+ classpath classpath
+
+ // dexClasspath is the list of jars that form the classpath for d8 and r8 rules. It contains
+ // header jars for all non-static dependencies. Static dependencies have already been
+ // combined into the program jar.
+ dexClasspath classpath
+
+ // java9Classpath is the list of jars that will be added to the classpath when targeting
+ // 1.9 or higher. It generally contains the android.* classes, while the java.* classes
+ // are provided by systemModules.
java9Classpath classpath
- processorPath classpath
- processors []string
- systemModules *systemModules
- aidlFlags string
- aidlDeps android.Paths
- javaVersion javaVersion
+
+ processorPath classpath
+ processors []string
+ systemModules *systemModules
+ aidlFlags string
+ aidlDeps android.Paths
+ javaVersion javaVersion
errorProneExtraJavacFlags string
errorProneProcessorPath classpath
@@ -341,11 +355,8 @@ func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, idx
})
}
-func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
- srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
-
+func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags) (string, android.Paths) {
var deps android.Paths
- deps = append(deps, srcJars...)
classpath := flags.classpath
@@ -367,20 +378,31 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.
}
deps = append(deps, classpath...)
- deps = append(deps, flags.processorPath...)
+ turbineFlags := bootClasspath + " " + classpath.FormTurbineClassPath("--classpath ")
+
+ return turbineFlags, deps
+}
+
+func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
+
+ turbineFlags, deps := turbineFlags(ctx, flags)
+
+ deps = append(deps, srcJars...)
rule := turbine
args := map[string]string{
- "javacFlags": flags.javacFlags,
- "bootClasspath": bootClasspath,
- "srcJars": strings.Join(srcJars.Strings(), " "),
- "classpath": classpath.FormTurbineClassPath("--classpath "),
- "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(),
- "javaVersion": flags.javaVersion.String(),
+ "javacFlags": flags.javacFlags,
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "javaVersion": flags.javaVersion.String(),
+ "turbineFlags": turbineFlags,
+ "outputFlags": "--output " + outputFile.String() + ".tmp",
+ "outputs": outputFile.String(),
}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
rule = turbineRE
args["implicits"] = strings.Join(deps.Strings(), ",")
+ args["rbeOutputs"] = outputFile.String() + ".tmp"
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
@@ -392,6 +414,47 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.
})
}
+// TurbineApt produces a rule to run annotation processors using turbine.
+func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
+
+ turbineFlags, deps := turbineFlags(ctx, flags)
+
+ deps = append(deps, srcJars...)
+
+ deps = append(deps, flags.processorPath...)
+ turbineFlags += " " + flags.processorPath.FormTurbineClassPath("--processorpath ")
+ turbineFlags += " --processors " + strings.Join(flags.processors, " ")
+
+ outputs := android.WritablePaths{outputSrcJar, outputResJar}
+ outputFlags := "--gensrc_output " + outputSrcJar.String() + ".tmp " +
+ "--resource_output " + outputResJar.String() + ".tmp"
+
+ rule := turbine
+ args := map[string]string{
+ "javacFlags": flags.javacFlags,
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "javaVersion": flags.javaVersion.String(),
+ "turbineFlags": turbineFlags,
+ "outputFlags": outputFlags,
+ "outputs": strings.Join(outputs.Strings(), " "),
+ }
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
+ rule = turbineRE
+ args["implicits"] = strings.Join(deps.Strings(), ",")
+ args["rbeOutputs"] = outputSrcJar.String() + ".tmp," + outputResJar.String() + ".tmp"
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: "turbine apt",
+ Output: outputs[0],
+ ImplicitOutputs: outputs[1:],
+ Inputs: srcFiles,
+ Implicits: deps,
+ Args: args,
+ })
+}
+
// transformJavaToClasses takes source files and converts them to a jar containing .class files.
// srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain
// sources. flags contains various command line flags to be passed to the compiler.
@@ -653,6 +716,6 @@ func (x *systemModules) FormTurbineSystemModulesPath(forceEmpty bool) (string, a
} else if forceEmpty {
return `--bootclasspath ""`, nil
} else {
- return "", nil
+ return "--system ${config.JavaHome}", nil
}
}
diff --git a/java/config/config.go b/java/config/config.go
index 05dfde635..95b841fa7 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -26,7 +26,8 @@ import (
)
var (
- pctx = android.NewPackageContext("android/soong/java/config")
+ pctx = android.NewPackageContext("android/soong/java/config")
+ exportedVars = android.NewExportedVariables(pctx)
LegacyCorePlatformBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"}
LegacyCorePlatformSystemModules = "legacy-core-platform-api-stubs-system-modules"
@@ -50,33 +51,43 @@ var (
"core-icu4j",
"core-oj",
"core-libart",
- // TODO: Could this be all updatable bootclasspath jars?
- "updatable-media",
- "framework-mediaprovider",
- "framework-sdkextensions",
- "android.net.ipsec.ike",
}
)
-const (
- JavaVmFlags = `-XX:OnError="cat hs_err_pid%p.log" -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads`
- JavacVmFlags = `-J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1`
+var (
+ JavacVmFlags = strings.Join(javacVmFlagsList, " ")
+ javaVmFlagsList = []string{
+ `-XX:OnError="cat hs_err_pid%p.log"`,
+ "-XX:CICompilerCount=6",
+ "-XX:+UseDynamicNumberOfGCThreads",
+ }
+ javacVmFlagsList = []string{
+ `-J-XX:OnError="cat hs_err_pid%p.log"`,
+ "-J-XX:CICompilerCount=6",
+ "-J-XX:+UseDynamicNumberOfGCThreads",
+ "-J-XX:+TieredCompilation",
+ "-J-XX:TieredStopAtLevel=1",
+ }
)
func init() {
pctx.Import("github.com/google/blueprint/bootstrap")
- pctx.StaticVariable("JavacHeapSize", "2048M")
- pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
+ exportedVars.ExportStringStaticVariable("JavacHeapSize", "2048M")
+ exportedVars.ExportStringStaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
// ErrorProne can use significantly more memory than javac alone, give it a higher heap
// size (b/221480398).
- pctx.StaticVariable("ErrorProneHeapSize", "4096M")
- pctx.StaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
+ exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "4096M")
+ exportedVars.ExportStringStaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
- pctx.StaticVariable("DexFlags", "-JXX:OnError='cat hs_err_pid%p.log' -JXX:CICompilerCount=6 -JXX:+UseDynamicNumberOfGCThreads")
+ exportedVars.ExportStringListStaticVariable("DexFlags", []string{
+ `-JXX:OnError="cat hs_err_pid%p.log"`,
+ "-JXX:CICompilerCount=6",
+ "-JXX:+UseDynamicNumberOfGCThreads",
+ })
- pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
+ exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{
`-Xmaxerrs 9999999`,
`-encoding UTF-8`,
`-sourcepath ""`,
@@ -90,10 +101,10 @@ func init() {
// b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9
`-XDstringConcat=inline`,
- }, " "))
+ })
- pctx.StaticVariable("JavaVmFlags", JavaVmFlags)
- pctx.StaticVariable("JavacVmFlags", JavacVmFlags)
+ exportedVars.ExportStringListStaticVariable("JavaVmFlags", javaVmFlagsList)
+ exportedVars.ExportStringListStaticVariable("JavacVmFlags", javacVmFlagsList)
pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
@@ -189,6 +200,10 @@ func init() {
hostJNIToolVariableWithSdkToolsPrebuilt("SignapkJniLibrary", "libconscrypt_openjdk_jni")
}
+func BazelJavaToolchainVars(config android.Config) string {
+ return android.BazelToolchainVars(config, exportedVars)
+}
+
func hostBinToolVariableWithSdkToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
if ctx.Config().AlwaysUsePrebuiltSdks() {
diff --git a/java/config/error_prone.go b/java/config/error_prone.go
index 48681b5c9..5f853c812 100644
--- a/java/config/error_prone.go
+++ b/java/config/error_prone.go
@@ -16,8 +16,6 @@ package config
import (
"strings"
-
- "android/soong/android"
)
var (
@@ -31,23 +29,23 @@ var (
)
// Wrapper that grabs value of val late so it can be initialized by a later module's init function
-func errorProneVar(name string, val *[]string, sep string) {
- pctx.VariableFunc(name, func(android.PackageVarContext) string {
+func errorProneVar(val *[]string, sep string) func() string {
+ return func() string {
return strings.Join(*val, sep)
- })
+ }
}
func init() {
- errorProneVar("ErrorProneClasspath", &ErrorProneClasspath, ":")
- errorProneVar("ErrorProneChecksError", &ErrorProneChecksError, " ")
- errorProneVar("ErrorProneChecksWarning", &ErrorProneChecksWarning, " ")
- errorProneVar("ErrorProneChecksDefaultDisabled", &ErrorProneChecksDefaultDisabled, " ")
- errorProneVar("ErrorProneChecksOff", &ErrorProneChecksOff, " ")
- errorProneVar("ErrorProneFlags", &ErrorProneFlags, " ")
- pctx.StaticVariable("ErrorProneChecks", strings.Join([]string{
+ exportedVars.ExportVariableFuncVariable("ErrorProneClasspath", errorProneVar(&ErrorProneClasspath, ":"))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksError", errorProneVar(&ErrorProneChecksError, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksWarning", errorProneVar(&ErrorProneChecksWarning, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksDefaultDisabled", errorProneVar(&ErrorProneChecksDefaultDisabled, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksOff", errorProneVar(&ErrorProneChecksOff, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneFlags", errorProneVar(&ErrorProneFlags, " "))
+ exportedVars.ExportStringListStaticVariable("ErrorProneChecks", []string{
"${ErrorProneChecksOff}",
"${ErrorProneChecksError}",
"${ErrorProneChecksWarning}",
"${ErrorProneChecksDefaultDisabled}",
- }, " "))
+ })
}
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index 6cb61f306..fc63f4dfb 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -34,6 +34,7 @@ func init() {
pctx.SourcePathVariable("KotlinKaptJar", "external/kotlinc/lib/kotlin-annotation-processing.jar")
pctx.SourcePathVariable("KotlinAnnotationJar", "external/kotlinc/lib/annotations-13.0.jar")
pctx.SourcePathVariable("KotlinStdlibJar", KotlinStdlibJar)
+ pctx.SourcePathVariable("KotlinAbiGenPluginJar", "external/kotlinc/lib/jvm-abi-gen.jar")
// These flags silence "Illegal reflective access" warnings when running kapt in OpenJDK9+
pctx.StaticVariable("KaptSuppressJDK9Warnings", strings.Join([]string{
@@ -47,4 +48,9 @@ func init() {
pctx.StaticVariable("KotlincSuppressJDK9Warnings", strings.Join([]string{
"-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704
}, " "))
+
+ pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{
+ // b/222162908: prevent kotlinc from reading /tmp/build.txt
+ "-Didea.plugins.compatible.build=999.SNAPSHOT",
+ }, " "))
}
diff --git a/java/dex.go b/java/dex.go
index 474694a51..84665e7b5 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -132,12 +132,15 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
`--no-data-resources ` +
`-printmapping ${outDict} ` +
`-printusage ${outUsage} ` +
+ `--deps-file ${out}.d ` +
`$r8Flags && ` +
`touch "${outDict}" "${outUsage}" && ` +
`${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
`rm -rf ${outUsageDir} && ` +
`$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`,
+ Depfile: "${out}.d",
+ Deps: blueprint.DepsGCC,
CommandDeps: []string{
"${config.R8Cmd}",
"${config.Zip2ZipCmd}",
@@ -205,10 +208,10 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) {
d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
- d8Flags = append(d8Flags, flags.classpath.FormRepeatedClassPath("--lib ")...)
+ d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...)
d8Deps = append(d8Deps, flags.bootClasspath...)
- d8Deps = append(d8Deps, flags.classpath...)
+ d8Deps = append(d8Deps, flags.dexClasspath...)
return d8Flags, d8Deps
}
@@ -231,11 +234,11 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
- r8Flags = append(r8Flags, flags.classpath.FormJavaClassPath("-libraryjars"))
+ r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
r8Deps = append(r8Deps, proguardRaiseDeps...)
r8Deps = append(r8Deps, flags.bootClasspath...)
- r8Deps = append(r8Deps, flags.classpath...)
+ r8Deps = append(r8Deps, flags.dexClasspath...)
flagFiles := android.Paths{
android.PathForSource(ctx, "build/make/core/proguard.flags"),
diff --git a/java/dex_test.go b/java/dex_test.go
new file mode 100644
index 000000000..fbdccb65d
--- /dev/null
+++ b/java/dex_test.go
@@ -0,0 +1,103 @@
+// 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 java
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestR8(t *testing.T) {
+ result := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd.RunTestWithBp(t, `
+ android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ libs: ["lib"],
+ static_libs: ["static_lib"],
+ platform_apis: true,
+ }
+
+ java_library {
+ name: "lib",
+ srcs: ["foo.java"],
+ }
+
+ java_library {
+ name: "static_lib",
+ srcs: ["foo.java"],
+ }
+ `)
+
+ app := result.ModuleForTests("app", "android_common")
+ lib := result.ModuleForTests("lib", "android_common")
+ staticLib := result.ModuleForTests("static_lib", "android_common")
+
+ appJavac := app.Rule("javac")
+ appR8 := app.Rule("r8")
+ libHeader := lib.Output("turbine-combined/lib.jar").Output
+ staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output
+
+ android.AssertStringDoesContain(t, "expected lib header jar in app javac classpath",
+ appJavac.Args["classpath"], libHeader.String())
+ android.AssertStringDoesContain(t, "expected static_lib header jar in app javac classpath",
+ appJavac.Args["classpath"], staticLibHeader.String())
+
+ android.AssertStringDoesContain(t, "expected lib header jar in app r8 classpath",
+ appR8.Args["r8Flags"], libHeader.String())
+ android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app javac classpath",
+ appR8.Args["r8Flags"], staticLibHeader.String())
+}
+
+func TestD8(t *testing.T) {
+ result := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd.RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ libs: ["lib"],
+ static_libs: ["static_lib"],
+ installable: true,
+ }
+
+ java_library {
+ name: "lib",
+ srcs: ["foo.java"],
+ }
+
+ java_library {
+ name: "static_lib",
+ srcs: ["foo.java"],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ lib := result.ModuleForTests("lib", "android_common")
+ staticLib := result.ModuleForTests("static_lib", "android_common")
+
+ fooJavac := foo.Rule("javac")
+ fooD8 := foo.Rule("d8")
+ libHeader := lib.Output("turbine-combined/lib.jar").Output
+ staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output
+
+ android.AssertStringDoesContain(t, "expected lib header jar in foo javac classpath",
+ fooJavac.Args["classpath"], libHeader.String())
+ android.AssertStringDoesContain(t, "expected static_lib header jar in foo javac classpath",
+ fooJavac.Args["classpath"], staticLibHeader.String())
+
+ android.AssertStringDoesContain(t, "expected lib header jar in foo d8 classpath",
+ fooD8.Args["d8Flags"], libHeader.String())
+ android.AssertStringDoesNotContain(t, "expected no static_lib header jar in foo javac classpath",
+ fooD8.Args["d8Flags"], staticLibHeader.String())
+}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 2921c3e82..3b1f7c041 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -433,6 +433,10 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a
}
}
+func metalavaUseRbe(ctx android.ModuleContext) bool {
+ return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
+}
+
func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
@@ -441,7 +445,7 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
cmd := rule.Command()
cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
+ if metalavaUseRbe(ctx) {
rule.Remoteable(android.RemoteRuleSupports{RBE: true})
execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
labels := map[string]string{"type": "tool", "name": "metalava"}
@@ -477,7 +481,7 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
Flag("--format=v2").
FlagWithArg("--repeat-errors-max ", "10").
FlagWithArg("--hide ", "UnresolvedImport").
- FlagWithArg("--hide ", "InvalidNullability").
+ FlagWithArg("--hide ", "InvalidNullabilityOverride").
// b/223382732
FlagWithArg("--hide ", "ChangedDefault")
@@ -665,7 +669,9 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
// TODO(b/183630617): rewrapper doesn't support restat rules
- // rule.Restat()
+ if !metalavaUseRbe(ctx) {
+ rule.Restat()
+ }
zipSyncCleanupCmd(rule, srcJarDir)
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 95ded34bb..534a8145f 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -295,6 +295,12 @@ func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.
return dexJar.Path()
}
+// HIDDENAPI_STUB_FLAGS_IMPL_FLAGS is the set of flags that identify implementation only signatures,
+// i.e. those signatures that are not part of any API (including the hidden API).
+var HIDDENAPI_STUB_FLAGS_IMPL_FLAGS = []string{}
+
+var HIDDENAPI_FLAGS_CSV_IMPL_FLAGS = []string{"blocked"}
+
// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
@@ -345,7 +351,8 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name,
// If there are stub flag files that have been generated by fragments on which this depends then
// use them to validate the stub flag file generated by the rules created by this method.
if len(stubFlagSubsets) > 0 {
- validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets)
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets,
+ HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
// Add the file that indicates that the file generated by this is valid.
//
@@ -904,7 +911,8 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
// If there are flag files that have been generated by fragments on which this depends then use
// them to validate the flag file generated by the rules created by this method.
if len(flagSubsets) > 0 {
- validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets)
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets,
+ HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
// Add the file that indicates that the file generated by this is valid.
//
@@ -968,13 +976,29 @@ func buildRuleSignaturePatternsFile(
return patternsFile
}
-// buildRuleRemoveBlockedFlag creates a rule that will remove entries from the input path which
-// only have blocked flags. It will not remove entries that have blocked as well as other flags,
-// e.g. blocked,core-platform-api.
-func buildRuleRemoveBlockedFlag(ctx android.BuilderContext, name string, desc string, inputPath android.Path, filteredPath android.WritablePath) {
+// buildRuleRemoveSignaturesWithImplementationFlags creates a rule that will remove signatures from
+// the input flags file which have only the implementation flags, i.e. are not part of an API.
+//
+// The implementationFlags specifies the set of default flags that identifies the signature of a
+// private, implementation only, member. Signatures that match those flags are removed from the
+// flags as they are implementation only.
+//
+// This is used to remove implementation only signatures from the signature files that are persisted
+// in the sdk snapshot as the sdk snapshots should not include implementation details. The
+// signatures generated by this method will be compared by the buildRuleValidateOverlappingCsvFiles
+// method which treats any missing signatures as if they were implementation only signatures.
+func buildRuleRemoveSignaturesWithImplementationFlags(ctx android.BuilderContext,
+ name string, desc string, inputPath android.Path, filteredPath android.WritablePath,
+ implementationFlags []string) {
+
rule := android.NewRuleBuilder(pctx, ctx)
+ implementationFlagPattern := ""
+ for _, implementationFlag := range implementationFlags {
+ implementationFlagPattern = implementationFlagPattern + "," + implementationFlag
+ }
rule.Command().
- Text(`grep -vE "^[^,]+,blocked$"`).Input(inputPath).Text(">").Output(filteredPath).
+ Text(`grep -vE "^[^,]+` + implementationFlagPattern + `$"`).Input(inputPath).
+ Text(">").Output(filteredPath).
// Grep's exit code depends on whether it finds anything. It is 0 (build success) when it finds
// something and 1 (build failure) when it does not and 2 (when it encounters an error).
// However, while it is unlikely it is not an error if this does not find any matches. The
@@ -986,7 +1010,14 @@ func buildRuleRemoveBlockedFlag(ctx android.BuilderContext, name string, desc st
// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
-func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets) android.WritablePath {
+//
+// The implementationFlags specifies the set of default flags that identifies the signature of a
+// private, implementation only, member. A signature which is present in a monolithic flags subset
+// defined by SignatureCsvSubset but which is not present in the flags file from the corresponding
+// module is assumed to be an implementation only member and so must have these flags.
+func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string,
+ monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets,
+ implementationFlags []string) android.WritablePath {
// The file which is used to record that the flags file is valid.
validFile := pathForValidation(ctx, monolithicFilePath)
@@ -994,14 +1025,19 @@ func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name strin
rule := android.NewRuleBuilder(pctx, ctx)
command := rule.Command().
BuiltTool("verify_overlaps").
- Input(monolithicFilePath)
+ FlagWithInput("--monolithic-flags ", monolithicFilePath)
for _, subset := range csvSubsets {
command.
+ Flag("--module-flags ").
Textf("%s:%s", subset.CsvFile, subset.SignaturePatternsFile).
Implicit(subset.CsvFile).Implicit(subset.SignaturePatternsFile)
}
+ for _, implementationFlag := range implementationFlags {
+ command.FlagWithArg("--implementation-flag ", implementationFlag)
+ }
+
// If validation passes then update the file that records that.
command.Text("&& touch").Output(validFile)
rule.Build(name+"Validation", desc+" validation")
@@ -1075,12 +1111,16 @@ func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents
// Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
// compared against the monolithic stub flags.
filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
- buildRuleRemoveBlockedFlag(ctx, "modularHiddenApiFilteredStubFlags", "modular hiddenapi filtered stub flags", stubFlagsCSV, filteredStubFlagsCSV)
+ buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags",
+ "modular hiddenapi filtered stub flags", stubFlagsCSV, filteredStubFlagsCSV,
+ HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
// Generate the filtered-flags.csv file which contains the filtered flags that will be compared
// against the monolithic flags.
filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
- buildRuleRemoveBlockedFlag(ctx, "modularHiddenApiFilteredFlags", "modular hiddenapi filtered flags", allFlagsCSV, filteredFlagsCSV)
+ buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags",
+ "modular hiddenapi filtered flags", allFlagsCSV, filteredFlagsCSV,
+ HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
// Store the paths in the info for use by other modules and sdk snapshot generation.
output := HiddenAPIOutput{
diff --git a/java/java.go b/java/java.go
index 895ce7af1..b34d6de8a 100644
--- a/java/java.go
+++ b/java/java.go
@@ -421,9 +421,25 @@ func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext,
}
type deps struct {
- classpath classpath
- java9Classpath classpath
- bootClasspath classpath
+ // bootClasspath is the list of jars that form the boot classpath (generally the java.* and
+ // android.* classes) for tools that still use it. javac targeting 1.9 or higher uses
+ // systemModules and java9Classpath instead.
+ bootClasspath classpath
+
+ // classpath is the list of jars that form the classpath for javac and kotlinc rules. It
+ // contains header jars for all static and non-static dependencies.
+ classpath classpath
+
+ // dexClasspath is the list of jars that form the classpath for d8 and r8 rules. It contains
+ // header jars for all non-static dependencies. Static dependencies have already been
+ // combined into the program jar.
+ dexClasspath classpath
+
+ // java9Classpath is the list of jars that will be added to the classpath when targeting
+ // 1.9 or higher. It generally contains the android.* classes, while the java.* classes
+ // are provided by systemModules.
+ java9Classpath classpath
+
processorPath classpath
errorProneProcessorPath classpath
processorClasses []string
@@ -1458,7 +1474,10 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
switch tag {
- case libTag, staticLibTag:
+ case libTag:
+ flags.classpath = append(flags.classpath, dep.HeaderJars...)
+ flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
+ case staticLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
case bootClasspathTag:
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
@@ -1706,6 +1725,7 @@ func ImportFactoryHost() android.Module {
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
+ android.InitBazelModule(module)
InitJavaModule(module, android.HostSupported)
return module
}
@@ -2004,13 +2024,28 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
}
}
-type javaLibraryAttributes struct {
+type javaCommonAttributes struct {
Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
+ Plugins bazel.LabelListAttribute
Javacopts bazel.StringListAttribute
}
-func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) *javaLibraryAttributes {
+type javaDependencyLabels struct {
+ // Dependencies which DO NOT contribute to the API visible to upstream dependencies.
+ Deps bazel.LabelListAttribute
+ // Dependencies which DO contribute to the API visible to upstream dependencies.
+ StaticDeps bazel.LabelListAttribute
+}
+
+// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
+// and also separates dependencies into dynamic dependencies and static dependencies.
+// Each corresponding Bazel target type, can have a different method for handling
+// dynamic vs. static dependencies, and so these are returned to the calling function.
+type eventLogTagsAttributes struct {
+ Srcs bazel.LabelListAttribute
+}
+
+func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) {
var srcs bazel.LabelListAttribute
archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
for axis, configToProps := range archVariantProps {
@@ -2024,45 +2059,104 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
javaSrcPartition := "java"
protoSrcPartition := "proto"
+ logtagSrcPartition := "logtag"
srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
- javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
- protoSrcPartition: android.ProtoSrcLabelPartition,
+ javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
+ logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
+ protoSrcPartition: android.ProtoSrcLabelPartition,
})
- attrs := &javaLibraryAttributes{
- Srcs: srcPartitions[javaSrcPartition],
+ javaSrcs := srcPartitions[javaSrcPartition]
+
+ var logtagsSrcs bazel.LabelList
+ if !srcPartitions[logtagSrcPartition].IsEmpty() {
+ logtagsLibName := m.Name() + "_logtags"
+ logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "event_log_tags",
+ Bzl_load_location: "//build/make/tools:event_log_tags.bzl",
+ },
+ android.CommonAttributes{Name: logtagsLibName},
+ &eventLogTagsAttributes{
+ Srcs: srcPartitions[logtagSrcPartition],
+ },
+ )
+ }
+ javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
+
+ var javacopts []string
+ if m.properties.Javacflags != nil {
+ javacopts = append(javacopts, m.properties.Javacflags...)
+ }
+ epEnabled := m.properties.Errorprone.Enabled
+ //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
+ if Bool(epEnabled) {
+ javacopts = append(javacopts, m.properties.Errorprone.Javacflags...)
}
- if m.properties.Javacflags != nil {
- attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
+ commonAttrs := &javaCommonAttributes{
+ Srcs: javaSrcs,
+ Plugins: bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
+ ),
+ Javacopts: bazel.MakeStringListAttribute(javacopts),
}
+ depLabels := &javaDependencyLabels{}
+
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))
}
+
+ var staticDeps bazel.LabelList
if m.properties.Static_libs != nil {
- //TODO(b/217236083) handle static libs similarly to Soong
- deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs))
+ staticDeps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs))
}
- protoDeps := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
- if protoDeps != nil {
- deps.Add(protoDeps)
- }
+ protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
+ // Soong does not differentiate between a java_library and the Bazel equivalent of
+ // a java_proto_library + proto_library pair. Instead, in Soong proto sources are
+ // listed directly in the srcs of a java_library, and the classes produced
+ // by protoc are included directly in the resulting JAR. Thus upstream dependencies
+ // that depend on a java_library with proto sources can link directly to the protobuf API,
+ // and so this should be a static dependency.
+ staticDeps.Add(protoDepLabel)
- attrs.Deps = bazel.MakeLabelListAttribute(deps)
+ depLabels.Deps = bazel.MakeLabelListAttribute(deps)
+ depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
- return attrs
+ return commonAttrs, depLabels
+}
+
+type javaLibraryAttributes struct {
+ *javaCommonAttributes
+ Deps bazel.LabelListAttribute
+ Exports bazel.LabelListAttribute
}
func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
- attrs := m.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
+
+ deps := depLabels.Deps
+ if !commonAttrs.Srcs.IsEmpty() {
+ deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
+
+ 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.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import"))
+ }
+ } else if !depLabels.Deps.IsEmpty() {
+ ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
+ }
+
+ attrs := &javaLibraryAttributes{
+ javaCommonAttributes: commonAttrs,
+ Deps: deps,
+ Exports: depLabels.StaticDeps,
+ }
props := bazel.BazelTargetModuleProperties{
Rule_class: "java_library",
@@ -2073,15 +2167,30 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
}
type javaBinaryHostAttributes struct {
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Main_class string
- Jvm_flags bazel.StringListAttribute
- Javacopts bazel.StringListAttribute
+ *javaCommonAttributes
+ Deps bazel.LabelListAttribute
+ Runtime_deps bazel.LabelListAttribute
+ Main_class string
+ Jvm_flags bazel.StringListAttribute
}
// JavaBinaryHostBp2Build is for java_binary_host bp2build.
func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
+ commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
+
+ deps := depLabels.Deps
+ deps.Append(depLabels.StaticDeps)
+ if m.binaryProperties.Jni_libs != nil {
+ deps.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs)))
+ }
+
+ var runtimeDeps bazel.LabelListAttribute
+ if commonAttrs.Srcs.IsEmpty() {
+ // if there are no sources, then the dependencies can only be used at runtime
+ runtimeDeps = deps
+ deps = bazel.LabelListAttribute{}
+ }
+
mainClass := ""
if m.binaryProperties.Main_class != nil {
mainClass = *m.binaryProperties.Main_class
@@ -2093,26 +2202,12 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
}
mainClass = mainClassInManifest
}
- srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs))
- attrs := &javaBinaryHostAttributes{
- Srcs: srcs,
- Main_class: mainClass,
- }
- if m.properties.Javacflags != nil {
- attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
- }
-
- // Attribute deps
- deps := []string{}
- if m.properties.Static_libs != nil {
- deps = append(deps, m.properties.Static_libs...)
- }
- if m.binaryProperties.Jni_libs != nil {
- deps = append(deps, m.binaryProperties.Jni_libs...)
- }
- if len(deps) > 0 {
- attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, deps))
+ attrs := &javaBinaryHostAttributes{
+ javaCommonAttributes: commonAttrs,
+ Deps: deps,
+ Runtime_deps: runtimeDeps,
+ Main_class: mainClass,
}
// Attribute jvm_flags
@@ -2155,8 +2250,16 @@ type bazelJavaImportAttributes struct {
// java_import bp2Build converter.
func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- //TODO(b/209577426): Support multiple arch variants
- jars := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, i.properties.Jars, []string(nil)))
+ var jars bazel.LabelListAttribute
+ archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{})
+ for axis, configToProps := range archVariantProps {
+ for config, _props := range configToProps {
+ if archProps, ok := _props.(*ImportProperties); ok {
+ archJars := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Jars, []string(nil))
+ jars.SetSelectValue(axis, config, archJars)
+ }
+ }
+ }
attrs := &bazelJavaImportAttributes{
Jars: jars,
diff --git a/java/java_test.go b/java/java_test.go
index f095c5e48..4c9382413 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -973,7 +973,7 @@ func TestTurbine(t *testing.T) {
fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
- android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["classpath"], fooHeaderJar)
+ android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["turbineFlags"], fooHeaderJar)
android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar)
android.AssertPathsRelativeToTopEquals(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs)
android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar")
diff --git a/java/jdeps.go b/java/jdeps.go
index eff9a3174..373433517 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -71,6 +71,8 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont
dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars)
dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars)
dpInfo.Paths = android.FirstUniqueStrings(dpInfo.Paths)
+ dpInfo.Static_libs = android.FirstUniqueStrings(dpInfo.Static_libs)
+ dpInfo.Libs = android.FirstUniqueStrings(dpInfo.Libs)
moduleInfos[name] = dpInfo
mkProvider, ok := module.(android.AndroidMkDataProvider)
diff --git a/java/kotlin.go b/java/kotlin.go
index e4f1bc198..eff5bb53f 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -28,16 +28,20 @@ import (
var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports{Goma: true},
blueprint.RuleParams{
- Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
- `mkdir -p "$classesDir" "$srcJarDir" "$emptyDir" && ` +
+ Command: `rm -rf "$classesDir" "$headerClassesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
+ `mkdir -p "$classesDir" "$headerClassesDir" "$srcJarDir" "$emptyDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
- `${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
- `$kotlincFlags -jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile ` +
- `-kotlin-home $emptyDir && ` +
- `${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir && ` +
+ `${config.KotlincCmd} ${config.KotlincGlobalFlags} ` +
+ ` ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
+ ` $kotlincFlags -jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile ` +
+ ` -kotlin-home $emptyDir ` +
+ ` -Xplugin=${config.KotlinAbiGenPluginJar} ` +
+ ` -P plugin:org.jetbrains.kotlin.jvm.abi:outputDir=$headerClassesDir && ` +
+ `${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir -write_if_changed && ` +
+ `${config.SoongZipCmd} -jar -o $headerJar -C $headerClassesDir -D $headerClassesDir -write_if_changed && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
"${config.KotlincCmd}",
@@ -48,15 +52,17 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports
"${config.KotlinStdlibJar}",
"${config.KotlinTrove4jJar}",
"${config.KotlinAnnotationJar}",
+ "${config.KotlinAbiGenPluginJar}",
"${config.GenKotlinBuildFileCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
},
Rspfile: "$out.rsp",
RspfileContent: `$in`,
+ Restat: true,
},
"kotlincFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "classesDir",
- "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name")
+ "headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name")
func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Paths) android.OptionalPath {
if len(commonSrcFiles) > 0 {
@@ -75,7 +81,7 @@ func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Path
}
// kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
-func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath,
+func kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile android.WritablePath,
srcFiles, commonSrcFiles, srcJars android.Paths,
flags javaBuilderFlags) {
@@ -96,17 +102,20 @@ func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath,
}
ctx.Build(pctx, android.BuildParams{
- Rule: kotlinc,
- Description: "kotlinc",
- Output: outputFile,
- Inputs: srcFiles,
- Implicits: deps,
+ Rule: kotlinc,
+ Description: "kotlinc",
+ Output: outputFile,
+ ImplicitOutput: headerOutputFile,
+ Inputs: srcFiles,
+ Implicits: deps,
Args: map[string]string{
"classpath": flags.kotlincClasspath.FormJavaClassPath(""),
"kotlincFlags": flags.kotlincFlags,
"commonSrcFilesArg": commonSrcFilesArg,
"srcJars": strings.Join(srcJars.Strings(), " "),
"classesDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
+ "headerClassesDir": android.PathForModuleOut(ctx, "kotlinc", "header_classes").String(),
+ "headerJar": headerOutputFile.String(),
"srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
"kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
"emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
@@ -117,7 +126,7 @@ func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath,
})
}
-var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: true},
+var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupports{Goma: true},
blueprint.RuleParams{
Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` +
`mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` +
@@ -125,19 +134,19 @@ var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma:
`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
` --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
- `${config.KotlincCmd} ${config.KaptSuppressJDK9Warnings} ${config.KotlincSuppressJDK9Warnings} ` +
+ `${config.KotlincCmd} ${config.KotlincGlobalFlags} ` +
+ `${config.KaptSuppressJDK9Warnings} ${config.KotlincSuppressJDK9Warnings} ` +
`${config.JavacHeapFlags} $kotlincFlags -Xplugin=${config.KotlinKaptJar} ` +
`-P plugin:org.jetbrains.kotlin.kapt3:sources=$kaptDir/sources ` +
`-P plugin:org.jetbrains.kotlin.kapt3:classes=$kaptDir/classes ` +
`-P plugin:org.jetbrains.kotlin.kapt3:stubs=$kaptDir/stubs ` +
`-P plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true ` +
- `-P plugin:org.jetbrains.kotlin.kapt3:aptMode=stubsAndApt ` +
+ `-P plugin:org.jetbrains.kotlin.kapt3:aptMode=stubs ` +
`-P plugin:org.jetbrains.kotlin.kapt3:javacArguments=$encodedJavacFlags ` +
`$kaptProcessorPath ` +
`$kaptProcessor ` +
`-Xbuild-file=$kotlinBuildFile && ` +
- `${config.SoongZipCmd} -jar -o $out -C $kaptDir/sources -D $kaptDir/sources && ` +
- `${config.SoongZipCmd} -jar -o $classesJarOut -C $kaptDir/classes -D $kaptDir/classes && ` +
+ `${config.SoongZipCmd} -jar -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
"${config.KotlincCmd}",
@@ -195,13 +204,14 @@ func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile an
kotlinName := filepath.Join(ctx.ModuleDir(), ctx.ModuleSubDir(), ctx.ModuleName())
kotlinName = strings.ReplaceAll(kotlinName, "/", "__")
+ // First run kapt to generate .java stubs from .kt files
+ kaptStubsJar := android.PathForModuleOut(ctx, "kapt", "stubs.jar")
ctx.Build(pctx, android.BuildParams{
- Rule: kapt,
- Description: "kapt",
- Output: srcJarOutputFile,
- ImplicitOutput: resJarOutputFile,
- Inputs: srcFiles,
- Implicits: deps,
+ Rule: kaptStubs,
+ Description: "kapt stubs",
+ Output: kaptStubsJar,
+ Inputs: srcFiles,
+ Implicits: deps,
Args: map[string]string{
"classpath": flags.kotlincClasspath.FormJavaClassPath(""),
"kotlincFlags": flags.kotlincFlags,
@@ -217,6 +227,11 @@ func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile an
"classesJarOut": resJarOutputFile.String(),
},
})
+
+ // Then run turbine to perform annotation processing on the stubs and any .java srcFiles.
+ javaSrcFiles := srcFiles.FilterByExt(".java")
+ turbineSrcJars := append(android.Paths{kaptStubsJar}, srcJars...)
+ TurbineApt(ctx, srcJarOutputFile, resJarOutputFile, javaSrcFiles, turbineSrcJars, flags)
}
// kapt converts a list of key, value pairs into a base64 encoded Java serialization, which is what kapt expects.
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index cac0af3b9..f9ff98229 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -45,6 +45,10 @@ func TestKotlin(t *testing.T) {
fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
+ fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
+
+ fooKotlincClasses := fooKotlinc.Output
+ fooKotlincHeaderClasses := fooKotlinc.ImplicitOutput
if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
fooKotlinc.Inputs[1].String() != "b.kt" {
@@ -55,17 +59,21 @@ func TestKotlin(t *testing.T) {
t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
}
- if !strings.Contains(fooJavac.Args["classpath"], fooKotlinc.Output.String()) {
+ if !strings.Contains(fooJavac.Args["classpath"], fooKotlincHeaderClasses.String()) {
t.Errorf("foo classpath %v does not contain %q",
- fooJavac.Args["classpath"], fooKotlinc.Output.String())
+ fooJavac.Args["classpath"], fooKotlincHeaderClasses.String())
}
- if !inList(fooKotlinc.Output.String(), fooJar.Inputs.Strings()) {
+ if !inList(fooKotlincClasses.String(), fooJar.Inputs.Strings()) {
t.Errorf("foo jar inputs %v does not contain %q",
- fooJar.Inputs.Strings(), fooKotlinc.Output.String())
+ fooJar.Inputs.Strings(), fooKotlincClasses.String())
+ }
+
+ if !inList(fooKotlincHeaderClasses.String(), fooHeaderJar.Inputs.Strings()) {
+ t.Errorf("foo header jar inputs %v does not contain %q",
+ fooHeaderJar.Inputs.Strings(), fooKotlincHeaderClasses.String())
}
- fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
@@ -117,51 +125,71 @@ func TestKapt(t *testing.T) {
buildOS := ctx.Config().BuildOS.String()
- kapt := ctx.ModuleForTests("foo", "android_common").Rule("kapt")
- kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ foo := ctx.ModuleForTests("foo", "android_common")
+ kaptStubs := foo.Rule("kapt")
+ turbineApt := foo.Description("turbine apt")
+ kotlinc := foo.Rule("kotlinc")
+ javac := foo.Rule("javac")
bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String()
// Test that the kotlin and java sources are passed to kapt and kotlinc
- if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" {
- t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kapt.Inputs)
+ if len(kaptStubs.Inputs) != 2 || kaptStubs.Inputs[0].String() != "a.java" || kaptStubs.Inputs[1].String() != "b.kt" {
+ t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kaptStubs.Inputs)
}
if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" || kotlinc.Inputs[1].String() != "b.kt" {
t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
}
- // Test that only the java sources are passed to javac
+ // Test that only the java sources are passed to turbine-apt and javac
+ if len(turbineApt.Inputs) != 1 || turbineApt.Inputs[0].String() != "a.java" {
+ t.Errorf(`foo turbine apt inputs %v != ["a.java"]`, turbineApt.Inputs)
+ }
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
}
- // Test that the kapt srcjar is a dependency of kotlinc and javac rules
- if !inList(kapt.Output.String(), kotlinc.Implicits.Strings()) {
- t.Errorf("expected %q in kotlinc implicits %v", kapt.Output.String(), kotlinc.Implicits.Strings())
+ // Test that the kapt stubs jar is a dependency of turbine-apt
+ if !inList(kaptStubs.Output.String(), turbineApt.Implicits.Strings()) {
+ t.Errorf("expected %q in turbine-apt implicits %v", kaptStubs.Output.String(), kotlinc.Implicits.Strings())
+ }
+
+ // Test that the turbine-apt srcjar is a dependency of kotlinc and javac rules
+ if !inList(turbineApt.Output.String(), kotlinc.Implicits.Strings()) {
+ t.Errorf("expected %q in kotlinc implicits %v", turbineApt.Output.String(), kotlinc.Implicits.Strings())
}
- if !inList(kapt.Output.String(), javac.Implicits.Strings()) {
- t.Errorf("expected %q in javac implicits %v", kapt.Output.String(), javac.Implicits.Strings())
+ if !inList(turbineApt.Output.String(), javac.Implicits.Strings()) {
+ t.Errorf("expected %q in javac implicits %v", turbineApt.Output.String(), javac.Implicits.Strings())
}
- // Test that the kapt srcjar is extracted by the kotlinc and javac rules
- if kotlinc.Args["srcJars"] != kapt.Output.String() {
- t.Errorf("expected %q in kotlinc srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
+ // Test that the turbine-apt srcjar is extracted by the kotlinc and javac rules
+ if kotlinc.Args["srcJars"] != turbineApt.Output.String() {
+ t.Errorf("expected %q in kotlinc srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
}
- if javac.Args["srcJars"] != kapt.Output.String() {
- t.Errorf("expected %q in javac srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
+ if javac.Args["srcJars"] != turbineApt.Output.String() {
+ t.Errorf("expected %q in javac srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
}
// Test that the processors are passed to kapt
expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
" -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
- if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
- t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
+ if kaptStubs.Args["kaptProcessorPath"] != expectedProcessorPath {
+ t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kaptStubs.Args["kaptProcessorPath"])
}
expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
- if kapt.Args["kaptProcessor"] != expectedProcessor {
- t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
+ if kaptStubs.Args["kaptProcessor"] != expectedProcessor {
+ t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kaptStubs.Args["kaptProcessor"])
+ }
+
+ // Test that the processors are passed to turbine-apt
+ expectedProcessorPath = "--processorpath " + bar + " " + baz
+ if !strings.Contains(turbineApt.Args["turbineFlags"], expectedProcessorPath) {
+ t.Errorf("expected turbine-apt processorpath %q, got %q", expectedProcessorPath, turbineApt.Args["turbineFlags"])
+ }
+ expectedProcessor = "--processors com.bar com.baz"
+ if !strings.Contains(turbineApt.Args["turbineFlags"], expectedProcessor) {
+ t.Errorf("expected turbine-apt processor %q, got %q", expectedProcessor, turbineApt.Args["turbineFlags"])
}
// Test that the processors are not passed to javac
diff --git a/java/lint.go b/java/lint.go
index 7845c336b..e97c9c225 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -102,12 +102,12 @@ type lintOutputsIntf interface {
lintOutputs() *lintOutputs
}
-type lintDepSetsIntf interface {
+type LintDepSetsIntf interface {
LintDepSets() LintDepSets
// Methods used to propagate strict_updatability_linting values.
- getStrictUpdatabilityLinting() bool
- setStrictUpdatabilityLinting(bool)
+ GetStrictUpdatabilityLinting() bool
+ SetStrictUpdatabilityLinting(bool)
}
type LintDepSets struct {
@@ -158,15 +158,15 @@ func (l *linter) LintDepSets() LintDepSets {
return l.outputs.depSets
}
-func (l *linter) getStrictUpdatabilityLinting() bool {
+func (l *linter) GetStrictUpdatabilityLinting() bool {
return BoolDefault(l.properties.Lint.Strict_updatability_linting, false)
}
-func (l *linter) setStrictUpdatabilityLinting(strictLinting bool) {
+func (l *linter) SetStrictUpdatabilityLinting(strictLinting bool) {
l.properties.Lint.Strict_updatability_linting = &strictLinting
}
-var _ lintDepSetsIntf = (*linter)(nil)
+var _ LintDepSetsIntf = (*linter)(nil)
var _ lintOutputsIntf = (*linter)(nil)
@@ -273,7 +273,7 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
- if l.getStrictUpdatabilityLinting() {
+ if l.GetStrictUpdatabilityLinting() {
// Verify the module does not baseline issues that endanger safe updatability.
if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() {
cmd.FlagWithInput("--baseline ", baselinePath.Path())
@@ -382,7 +382,7 @@ func (l *linter) lint(ctx android.ModuleContext) {
depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
- if depLint, ok := dep.(lintDepSetsIntf); ok {
+ if depLint, ok := dep.(LintDepSetsIntf); ok {
depSetsBuilder.Transitive(depLint.LintDepSets())
}
})
@@ -660,10 +660,10 @@ func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android
// Enforce the strict updatability linting to all applicable transitive dependencies.
func enforceStrictUpdatabilityLintingMutator(ctx android.TopDownMutatorContext) {
m := ctx.Module()
- if d, ok := m.(lintDepSetsIntf); ok && d.getStrictUpdatabilityLinting() {
+ if d, ok := m.(LintDepSetsIntf); ok && d.GetStrictUpdatabilityLinting() {
ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
- if a, ok := d.(lintDepSetsIntf); ok {
- a.setStrictUpdatabilityLinting(true)
+ if a, ok := d.(LintDepSetsIntf); ok {
+ a.SetStrictUpdatabilityLinting(true)
}
})
}
diff --git a/java/plugin.go b/java/plugin.go
index 4b174b930..123dbd4c0 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -58,27 +58,32 @@ type PluginProperties struct {
}
type pluginAttributes struct {
- *javaLibraryAttributes
- Processor_class *string
- Target_compatible_with bazel.LabelListAttribute
+ *javaCommonAttributes
+ Deps bazel.LabelListAttribute
+ Processor_class *string
}
// ConvertWithBp2build is used to convert android_app to Bazel.
func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- libAttrs := p.convertLibraryAttrsBp2Build(ctx)
- attrs := &pluginAttributes{
- libAttrs,
- nil,
- bazel.LabelListAttribute{},
- }
+ pluginName := p.Name()
+ commonAttrs, depLabels := p.convertLibraryAttrsBp2Build(ctx)
+
+ deps := depLabels.Deps
+ deps.Append(depLabels.StaticDeps)
+ var processorClass *string
if p.pluginProperties.Processor_class != nil {
- attrs.Processor_class = p.pluginProperties.Processor_class
+ processorClass = p.pluginProperties.Processor_class
+ }
+
+ attrs := &pluginAttributes{
+ javaCommonAttributes: commonAttrs,
+ Deps: deps,
+ Processor_class: processorClass,
}
props := bazel.BazelTargetModuleProperties{
Rule_class: "java_plugin",
}
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: p.Name()}, attrs)
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: pluginName}, attrs)
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index bfdfffcd9..c37ed1a27 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2362,17 +2362,17 @@ func (module *SdkLibraryImport) LintDepSets() LintDepSets {
}
}
-func (module *SdkLibraryImport) getStrictUpdatabilityLinting() bool {
+func (module *SdkLibraryImport) GetStrictUpdatabilityLinting() bool {
if module.implLibraryModule == nil {
return false
} else {
- return module.implLibraryModule.getStrictUpdatabilityLinting()
+ return module.implLibraryModule.GetStrictUpdatabilityLinting()
}
}
-func (module *SdkLibraryImport) setStrictUpdatabilityLinting(strictLinting bool) {
+func (module *SdkLibraryImport) SetStrictUpdatabilityLinting(strictLinting bool) {
if module.implLibraryModule != nil {
- module.implLibraryModule.setStrictUpdatabilityLinting(strictLinting)
+ module.implLibraryModule.SetStrictUpdatabilityLinting(strictLinting)
}
}
diff --git a/java/testing.go b/java/testing.go
index 82aa29b61..4000334b5 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -70,6 +70,10 @@ var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixtu
defaultJavaDir + "/framework/aidl": nil,
// Needed for various deps defined in GatherRequiredDepsForTest()
defaultJavaDir + "/a.java": nil,
+
+ // Needed for R8 rules on apps
+ "build/make/core/proguard.flags": nil,
+ "build/make/core/proguard_basic_keeps.flags": nil,
}.AddToFixture(),
// The java default module definitions.
android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),