Merge "Avoid hiddenapi ignoring prebuilt with missing dex implementation jar"
diff --git a/android/arch.go b/android/arch.go
index f719ddc..20b4ab0 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1615,3 +1615,97 @@
return buildTargets, nil
}
+
+// GetArchProperties returns a map of architectures to the values of the
+// properties of the 'dst' struct that are specific to that architecture.
+//
+// For example, passing a struct { Foo bool, Bar string } will return an
+// interface{} that can be type asserted back into the same struct, containing
+// the arch specific property value specified by the module if defined.
+func (m *ModuleBase) GetArchProperties(dst interface{}) map[ArchType]interface{} {
+ // Return value of the arch types to the prop values for that arch.
+ archToProp := map[ArchType]interface{}{}
+
+ // Nothing to do for non-arch-specific modules.
+ if !m.ArchSpecific() {
+ return archToProp
+ }
+
+ // archProperties has the type of [][]interface{}. Looks complicated, so let's
+ // explain this step by step.
+ //
+ // Loop over the outer index, which determines the property struct that
+ // contains a matching set of properties in dst that we're interested in.
+ // For example, BaseCompilerProperties or BaseLinkerProperties.
+ for i := range m.archProperties {
+ if m.archProperties[i] == nil {
+ // Skip over nil arch props
+ continue
+ }
+
+ // Non-nil arch prop, let's see if the props match up.
+ for _, arch := range ArchTypeList() {
+ // e.g X86, Arm
+ field := arch.Field
+
+ // If it's not nil, loop over the inner index, which determines the arch variant
+ // of the prop type. In an Android.bp file, this is like looping over:
+ //
+ // arch: { arm: { key: value, ... }, x86: { key: value, ... } }
+ for _, archProperties := range m.archProperties[i] {
+ archPropValues := reflect.ValueOf(archProperties).Elem()
+
+ // This is the archPropRoot struct. Traverse into the Arch nested struct.
+ src := archPropValues.FieldByName("Arch").Elem()
+
+ // Step into non-nil pointers to structs in the src value.
+ if src.Kind() == reflect.Ptr {
+ if src.IsNil() {
+ // Ignore nil pointers.
+ continue
+ }
+ src = src.Elem()
+ }
+
+ // Find the requested field (e.g. x86, x86_64) in the src struct.
+ src = src.FieldByName(field)
+ if !src.IsValid() {
+ continue
+ }
+
+ // We only care about structs. These are not the droids you are looking for.
+ if src.Kind() != reflect.Struct {
+ continue
+ }
+
+ // If the value of the field is a struct then step into the
+ // BlueprintEmbed field. The special "BlueprintEmbed" name is
+ // used by createArchPropTypeDesc to embed the arch properties
+ // in the parent struct, so the src arch prop should be in this
+ // field.
+ //
+ // See createArchPropTypeDesc for more details on how Arch-specific
+ // module properties are processed from the nested props and written
+ // into the module's archProperties.
+ src = src.FieldByName("BlueprintEmbed")
+
+ // Clone the destination prop, since we want a unique prop struct per arch.
+ dstClone := reflect.New(reflect.ValueOf(dst).Elem().Type()).Interface()
+
+ // Copy the located property struct into the cloned destination property struct.
+ err := proptools.ExtendMatchingProperties([]interface{}{dstClone}, src.Interface(), nil, proptools.OrderReplace)
+ if err != nil {
+ // This is fine, it just means the src struct doesn't match.
+ continue
+ }
+
+ // Found the prop for the arch, you have.
+ archToProp[arch] = dstClone
+
+ // Go to the next prop.
+ break
+ }
+ }
+ }
+ return archToProp
+}
diff --git a/android/module.go b/android/module.go
index 5342246..1936d3c 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1123,8 +1123,15 @@
variableProperties interface{}
hostAndDeviceProperties hostAndDeviceProperties
generalProperties []interface{}
- archProperties [][]interface{}
- customizableProperties []interface{}
+
+ // Arch specific versions of structs in generalProperties. The outer index
+ // has the same order as generalProperties as initialized in
+ // InitAndroidArchModule, and the inner index chooses the props specific to
+ // the architecture. The interface{} value is an archPropRoot that is
+ // filled with arch specific values by the arch mutator.
+ archProperties [][]interface{}
+
+ customizableProperties []interface{}
// Properties specific to the Blueprint to BUILD migration.
bazelTargetModuleProperties bazel.BazelTargetModuleProperties
diff --git a/bazel/properties.go b/bazel/properties.go
index a4df4bc..a5ffa55 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -14,6 +14,8 @@
package bazel
+import "fmt"
+
type bazelModuleProperties struct {
// The label of the Bazel target replacing this Soong module.
Label string
@@ -63,3 +65,72 @@
ll.Excludes = append(other.Excludes, other.Excludes...)
}
}
+
+// StringListAttribute corresponds to the string_list Bazel attribute type with
+// support for additional metadata, like configurations.
+type StringListAttribute struct {
+ // The base value of the string list attribute.
+ Value []string
+
+ // Optional additive set of list values to the base value.
+ ArchValues stringListArchValues
+}
+
+// Arch-specific string_list typed Bazel attribute values. This should correspond
+// to the types of architectures supported for compilation in arch.go.
+type stringListArchValues struct {
+ X86 []string
+ X86_64 []string
+ Arm []string
+ Arm64 []string
+ Default []string
+ // TODO(b/181299724): this is currently missing the "common" arch, which
+ // doesn't have an equivalent platform() definition yet.
+}
+
+// HasArchSpecificValues returns true if the attribute contains
+// architecture-specific string_list values.
+func (attrs *StringListAttribute) HasArchSpecificValues() bool {
+ for _, arch := range []string{"x86", "x86_64", "arm", "arm64", "default"} {
+ if len(attrs.GetValueForArch(arch)) > 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// GetValueForArch returns the string_list attribute value for an architecture.
+func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
+ switch arch {
+ case "x86":
+ return attrs.ArchValues.X86
+ case "x86_64":
+ return attrs.ArchValues.X86_64
+ case "arm":
+ return attrs.ArchValues.Arm
+ case "arm64":
+ return attrs.ArchValues.Arm64
+ case "default":
+ return attrs.ArchValues.Default
+ default:
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+}
+
+// SetValueForArch sets the string_list attribute value for an architecture.
+func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) {
+ switch arch {
+ case "x86":
+ attrs.ArchValues.X86 = value
+ case "x86_64":
+ attrs.ArchValues.X86_64 = value
+ case "arm":
+ attrs.ArchValues.Arm = value
+ case "arm64":
+ attrs.ArchValues.Arm64 = value
+ case "default":
+ attrs.ArchValues.Default = value
+ default:
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 7d748ec..8deb5a2 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -10,6 +10,7 @@
"bp2build.go",
"build_conversion.go",
"bzl_conversion.go",
+ "configurability.go",
"conversion.go",
"metrics.go",
],
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a4c4a0d..7fa4996 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -354,11 +354,42 @@
ret += makeIndent(indent)
ret += "]"
case reflect.Struct:
+ // Special cases where the bp2build sends additional information to the codegenerator
+ // by wrapping the attributes in a custom struct type.
if labels, ok := propertyValue.Interface().(bazel.LabelList); ok {
// TODO(b/165114590): convert glob syntax
return prettyPrint(reflect.ValueOf(labels.Includes), indent)
} else if label, ok := propertyValue.Interface().(bazel.Label); ok {
return fmt.Sprintf("%q", label.Label), nil
+ } else if stringList, ok := propertyValue.Interface().(bazel.StringListAttribute); ok {
+ // A Bazel string_list attribute that may contain a select statement.
+ ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent)
+ if err != nil {
+ return ret, err
+ }
+
+ if !stringList.HasArchSpecificValues() {
+ // Select statement not needed.
+ return ret, nil
+ }
+
+ ret += " + " + "select({\n"
+ for _, arch := range android.ArchTypeList() {
+ value := stringList.GetValueForArch(arch.Name)
+ if len(value) > 0 {
+ ret += makeIndent(indent + 1)
+ list, _ := prettyPrint(reflect.ValueOf(value), indent+1)
+ ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list)
+ }
+ }
+
+ ret += makeIndent(indent + 1)
+ list, _ := prettyPrint(reflect.ValueOf(stringList.GetValueForArch("default")), indent+1)
+ ret += fmt.Sprintf("\"%s\": %s,\n", "//conditions:default", list)
+
+ ret += makeIndent(indent)
+ ret += "})"
+ return ret, err
}
ret = "{\n"
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index f655842..1d4e322 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -99,15 +99,6 @@
cc_defaults {
name: "foo_defaults",
defaults: ["foo_bar_defaults"],
- // TODO(b/178130668): handle configurable attributes that depend on the platform
- arch: {
- x86: {
- cflags: ["-fPIC"],
- },
- x86_64: {
- cflags: ["-fPIC"],
- },
- },
}
cc_defaults {
@@ -233,3 +224,137 @@
}
}
}
+
+func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
+ testCases := []struct {
+ description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ blueprint string
+ expectedBazelTargets []string
+ filesystem map[string]string
+ }{
+ {
+ description: "cc_object setting cflags for one arch",
+ moduleTypeUnderTest: "cc_object",
+ moduleTypeUnderTestFactory: cc.ObjectFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ blueprint: `cc_object {
+ name: "foo",
+ arch: {
+ x86: {
+ cflags: ["-fPIC"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ `cc_object(
+ name = "foo",
+ copts = [
+ "-fno-addrsig",
+ ] + select({
+ "@bazel_tools//platforms:x86_32": [
+ "-fPIC",
+ ],
+ "//conditions:default": [
+ ],
+ }),
+)`,
+ },
+ },
+ {
+ description: "cc_object setting cflags for 4 architectures",
+ moduleTypeUnderTest: "cc_object",
+ moduleTypeUnderTestFactory: cc.ObjectFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ blueprint: `cc_object {
+ name: "foo",
+ arch: {
+ x86: {
+ cflags: ["-fPIC"],
+ },
+ x86_64: {
+ cflags: ["-fPIC"],
+ },
+ arm: {
+ cflags: ["-Wall"],
+ },
+ arm64: {
+ cflags: ["-Wall"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ `cc_object(
+ name = "foo",
+ copts = [
+ "-fno-addrsig",
+ ] + select({
+ "@bazel_tools//platforms:arm": [
+ "-Wall",
+ ],
+ "@bazel_tools//platforms:aarch64": [
+ "-Wall",
+ ],
+ "@bazel_tools//platforms:x86_32": [
+ "-fPIC",
+ ],
+ "@bazel_tools//platforms:x86_64": [
+ "-fPIC",
+ ],
+ "//conditions:default": [
+ ],
+ }),
+)`,
+ },
+ },
+ }
+
+ dir := "."
+ for _, testCase := range testCases {
+ filesystem := make(map[string][]byte)
+ toParse := []string{
+ "Android.bp",
+ }
+ config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
+ ctx := android.NewTestContext(config)
+ // Always register cc_defaults module factory
+ ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
+
+ ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+ ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, toParse)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+ _, errs = ctx.ResolveDependencies(config)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+ if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+ fmt.Println(bazelTargets)
+ t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+ } else {
+ for i, target := range bazelTargets {
+ if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ testCase.description,
+ w,
+ g,
+ )
+ }
+ }
+ }
+ }
+}
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
new file mode 100644
index 0000000..47cf3c6
--- /dev/null
+++ b/bp2build/configurability.go
@@ -0,0 +1,15 @@
+package bp2build
+
+import "android/soong/android"
+
+// Configurability support for bp2build.
+
+var (
+ // A map of architectures to the Bazel label of the constraint_value.
+ platformArchMap = map[android.ArchType]string{
+ android.Arm: "@bazel_tools//platforms:arm",
+ android.Arm64: "@bazel_tools//platforms:aarch64",
+ android.X86: "@bazel_tools//platforms:x86_32",
+ android.X86_64: "@bazel_tools//platforms:x86_64",
+ }
+)
diff --git a/cc/object.go b/cc/object.go
index 140a066..32347b8 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -93,7 +93,7 @@
type bazelObjectAttributes struct {
Srcs bazel.LabelList
Deps bazel.LabelList
- Copts []string
+ Copts bazel.StringListAttribute
Local_include_dirs []string
}
@@ -133,13 +133,14 @@
ctx.ModuleErrorf("compiler must not be nil for a cc_object module")
}
- var copts []string
+ // Set arch-specific configurable attributes
+ var copts bazel.StringListAttribute
var srcs []string
var excludeSrcs []string
var localIncludeDirs []string
for _, props := range m.compiler.compilerProps() {
if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
- copts = baseCompilerProps.Cflags
+ copts.Value = baseCompilerProps.Cflags
srcs = baseCompilerProps.Srcs
excludeSrcs = baseCompilerProps.Exclude_srcs
localIncludeDirs = baseCompilerProps.Local_include_dirs
@@ -154,6 +155,13 @@
}
}
+ for arch, p := range m.GetArchProperties(&BaseCompilerProperties{}) {
+ if cProps, ok := p.(*BaseCompilerProperties); ok {
+ copts.SetValueForArch(arch.Name, cProps.Cflags)
+ }
+ }
+ copts.SetValueForArch("default", []string{})
+
attrs := &bazelObjectAttributes{
Srcs: android.BazelLabelForModuleSrcExcludes(ctx, srcs, excludeSrcs),
Deps: deps,
diff --git a/java/Android.bp b/java/Android.bp
index 9bfd009..461b16d 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -58,7 +58,6 @@
"sdk_library.go",
"sdk_library_external.go",
"support_libraries.go",
- "sysprop.go",
"system_modules.go",
"testing.go",
"tradefed.go",
diff --git a/java/androidmk.go b/java/androidmk.go
index 9bdb70c..3d3eae5 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -220,7 +220,7 @@
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.maybeStrippedDexJarFile),
+ OutputFile: android.OptionalPathForPath(prebuilt.dexJarFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
diff --git a/java/app.go b/java/app.go
index 8287533..39f06d0 100755
--- a/java/app.go
+++ b/java/app.go
@@ -469,7 +469,7 @@
a.Module.compile(ctx, a.aaptSrcJar)
}
- return a.maybeStrippedDexJarFile
+ return a.dexJarFile
}
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
diff --git a/java/app_test.go b/java/app_test.go
index b1abe3d..349579e 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -685,6 +685,51 @@
}
}
+func TestAppJavaResources(t *testing.T) {
+ bp := `
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ java_resources: ["resources/a"],
+ srcs: ["a.java"],
+ }
+
+ android_app {
+ name: "bar",
+ sdk_version: "current",
+ java_resources: ["resources/a"],
+ }
+ `
+
+ ctx := testApp(t, bp)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+ fooResources := foo.Output("res/foo.jar")
+ fooDexJar := foo.Output("dex-withres/foo.jar")
+ fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar")
+ fooApk := foo.Rule("combineApk")
+
+ if g, w := fooDexJar.Inputs.Strings(), fooResources.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected resource jar %q in foo dex jar inputs %q", w, g)
+ }
+
+ if g, w := fooDexJarAligned.Input.String(), fooDexJar.Output.String(); g != w {
+ t.Errorf("expected dex jar %q in foo aligned dex jar inputs %q", w, g)
+ }
+
+ if g, w := fooApk.Inputs.Strings(), fooDexJarAligned.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g)
+ }
+
+ bar := ctx.ModuleForTests("bar", "android_common")
+ barResources := bar.Output("res/bar.jar")
+ barApk := bar.Rule("combineApk")
+
+ if g, w := barApk.Inputs.Strings(), barResources.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected resources jar %q in bar apk inputs %q", w, g)
+ }
+}
+
func TestAndroidResources(t *testing.T) {
testCases := []struct {
name string
diff --git a/java/java.go b/java/java.go
index 78cd362..e471f0d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -370,6 +370,10 @@
// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
// Defaults to false.
V4_signature *bool
+
+ // Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the
+ // public stubs library.
+ SyspropPublicStub string `blueprint:"mutated"`
}
// Functionality common to Module and Import
@@ -434,9 +438,6 @@
// output file containing classes.dex and resources
dexJarFile android.Path
- // output file that contains classes.dex if it should be in the output file
- maybeStrippedDexJarFile android.Path
-
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
@@ -583,6 +584,16 @@
var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})
+// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
+// the sysprop implementation library.
+type SyspropPublicStubInfo struct {
+ // JavaInfo is the JavaInfoProvider of the sysprop public stub library that corresponds to
+ // the sysprop implementation library.
+ JavaInfo JavaInfo
+}
+
+var SyspropPublicStubInfoProvider = blueprint.NewProvider(SyspropPublicStubInfo{})
+
// Methods that need to be implemented for a module that is added to apex java_libs property.
type ApexDependency interface {
HeaderJars() android.Paths
@@ -652,29 +663,30 @@
}
var (
- dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
- staticLibTag = dependencyTag{name: "staticlib"}
- libTag = dependencyTag{name: "javalib"}
- java9LibTag = dependencyTag{name: "java9lib"}
- pluginTag = dependencyTag{name: "plugin"}
- errorpronePluginTag = dependencyTag{name: "errorprone-plugin"}
- exportedPluginTag = dependencyTag{name: "exported-plugin"}
- bootClasspathTag = dependencyTag{name: "bootclasspath"}
- systemModulesTag = dependencyTag{name: "system modules"}
- frameworkResTag = dependencyTag{name: "framework-res"}
- kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
- kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
- proguardRaiseTag = dependencyTag{name: "proguard-raise"}
- certificateTag = dependencyTag{name: "certificate"}
- instrumentationForTag = dependencyTag{name: "instrumentation_for"}
- extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
- jniLibTag = dependencyTag{name: "jnilib"}
- jniInstallTag = installDependencyTag{name: "jni install"}
- binaryInstallTag = installDependencyTag{name: "binary install"}
- usesLibTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion)
- usesLibCompat28Tag = makeUsesLibraryDependencyTag(28)
- usesLibCompat29Tag = makeUsesLibraryDependencyTag(29)
- usesLibCompat30Tag = makeUsesLibraryDependencyTag(30)
+ dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
+ staticLibTag = dependencyTag{name: "staticlib"}
+ libTag = dependencyTag{name: "javalib"}
+ java9LibTag = dependencyTag{name: "java9lib"}
+ pluginTag = dependencyTag{name: "plugin"}
+ errorpronePluginTag = dependencyTag{name: "errorprone-plugin"}
+ exportedPluginTag = dependencyTag{name: "exported-plugin"}
+ bootClasspathTag = dependencyTag{name: "bootclasspath"}
+ systemModulesTag = dependencyTag{name: "system modules"}
+ frameworkResTag = dependencyTag{name: "framework-res"}
+ kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
+ kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
+ proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+ certificateTag = dependencyTag{name: "certificate"}
+ instrumentationForTag = dependencyTag{name: "instrumentation_for"}
+ extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
+ jniLibTag = dependencyTag{name: "jnilib"}
+ syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
+ jniInstallTag = installDependencyTag{name: "jni install"}
+ binaryInstallTag = installDependencyTag{name: "binary install"}
+ usesLibTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion)
+ usesLibCompat28Tag = makeUsesLibraryDependencyTag(28)
+ usesLibCompat29Tag = makeUsesLibraryDependencyTag(29)
+ usesLibCompat30Tag = makeUsesLibraryDependencyTag(30)
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -813,35 +825,17 @@
j.linter.deps(ctx)
sdkDeps(ctx, sdkContext(j), j.dexer)
- }
- syspropPublicStubs := syspropPublicStubs(ctx.Config())
-
- // rewriteSyspropLibs validates if a java module can link against platform's sysprop_library,
- // and redirects dependency to public stub depending on the link type.
- rewriteSyspropLibs := func(libs []string, prop string) []string {
- // make a copy
- ret := android.CopyOf(libs)
-
- for idx, lib := range libs {
- stub, ok := syspropPublicStubs[lib]
-
- if !ok {
- continue
- }
-
- linkType, _ := j.getLinkType(ctx.ModuleName())
- // only platform modules can use internal props
- if linkType != javaPlatform {
- ret[idx] = stub
- }
+ if j.deviceProperties.SyspropPublicStub != "" {
+ // This is a sysprop implementation library that has a corresponding sysprop public
+ // stubs library, and a dependency on it so that dependencies on the implementation can
+ // be forwarded to the public stubs library when necessary.
+ ctx.AddVariationDependencies(nil, syspropPublicStubDepTag, j.deviceProperties.SyspropPublicStub)
}
-
- return ret
}
- libDeps := ctx.AddVariationDependencies(nil, libTag, rewriteSyspropLibs(j.properties.Libs, "libs")...)
- ctx.AddVariationDependencies(nil, staticLibTag, rewriteSyspropLibs(j.properties.Static_libs, "static_libs")...)
+ libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
@@ -856,15 +850,11 @@
// if true, enable enforcement
// PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
// exception list of java_library names to allow inter-partition dependency
- for idx, lib := range j.properties.Libs {
+ for idx := range j.properties.Libs {
if libDeps[idx] == nil {
continue
}
- if _, ok := syspropPublicStubs[lib]; ok {
- continue
- }
-
if javaDep, ok := libDeps[idx].(javaSdkLibraryEnforceContext); ok {
// java_sdk_library is always allowed at inter-partition dependency.
// So, skip check.
@@ -1134,6 +1124,8 @@
}
}
+ linkType, _ := j.getLinkType(ctx.ModuleName())
+
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@@ -1156,6 +1148,14 @@
}
} else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if linkType != javaPlatform &&
+ ctx.OtherModuleHasProvider(module, SyspropPublicStubInfoProvider) {
+ // dep is a sysprop implementation library, but this module is not linking against
+ // the platform, so it gets the sysprop public stubs library instead. Replace
+ // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
+ syspropDep := ctx.OtherModuleProvider(module, SyspropPublicStubInfoProvider).(SyspropPublicStubInfo)
+ dep = syspropDep.JavaInfo
+ }
switch tag {
case bootClasspathTag:
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
@@ -1214,6 +1214,12 @@
deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...)
case kotlinAnnotationsTag:
deps.kotlinAnnotations = dep.HeaderJars
+ case syspropPublicStubDepTag:
+ // This is a sysprop implementation library, forward the JavaInfoProvider from
+ // the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
+ ctx.SetProvider(SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
+ JavaInfo: dep,
+ })
}
} else if dep, ok := module.(android.SourceFileProducer); ok {
switch tag {
@@ -1818,47 +1824,51 @@
}
}
- if ctx.Device() && j.hasCode(ctx) &&
- (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
- if j.shouldInstrumentStatic(ctx) {
- j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
- android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
- }
- // Dex compilation
- var dexOutputFile android.OutputPath
- dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
- if ctx.Failed() {
- return
- }
-
- // Hidden API CSV generation and dex encoding
- dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
- proptools.Bool(j.dexProperties.Uncompress_dex))
-
- // merge dex jar with resources if necessary
- if j.resourceJar != nil {
- jars := android.Paths{dexOutputFile, j.resourceJar}
- combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
- TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
- false, nil, nil)
- if *j.dexProperties.Uncompress_dex {
- combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
- TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
- dexOutputFile = combinedAlignedJar
- } else {
- dexOutputFile = combinedJar
+ if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
+ if j.hasCode(ctx) {
+ if j.shouldInstrumentStatic(ctx) {
+ j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
}
+ // Dex compilation
+ var dexOutputFile android.OutputPath
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
+ if ctx.Failed() {
+ return
+ }
+
+ // Hidden API CSV generation and dex encoding
+ dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
+ proptools.Bool(j.dexProperties.Uncompress_dex))
+
+ // merge dex jar with resources if necessary
+ if j.resourceJar != nil {
+ jars := android.Paths{dexOutputFile, j.resourceJar}
+ combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
+ TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ if *j.dexProperties.Uncompress_dex {
+ combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
+ TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+ dexOutputFile = combinedAlignedJar
+ } else {
+ dexOutputFile = combinedJar
+ }
+ }
+
+ j.dexJarFile = dexOutputFile
+
+ // Dexpreopting
+ j.dexpreopt(ctx, dexOutputFile)
+
+ outputFile = dexOutputFile
+ } else {
+ // There is no code to compile into a dex jar, make sure the resources are propagated
+ // to the APK if this is an app.
+ outputFile = implementationAndResourcesJar
+ j.dexJarFile = j.resourceJar
}
- j.dexJarFile = dexOutputFile
-
- // Dexpreopting
- j.dexpreopt(ctx, dexOutputFile)
-
- j.maybeStrippedDexJarFile = dexOutputFile
-
- outputFile = dexOutputFile
-
if ctx.Failed() {
return
}
@@ -3183,8 +3193,7 @@
properties DexImportProperties
- dexJarFile android.Path
- maybeStrippedDexJarFile android.Path
+ dexJarFile android.Path
dexpreopter
@@ -3271,8 +3280,6 @@
j.dexpreopt(ctx, dexOutputFile)
- j.maybeStrippedDexJarFile = dexOutputFile
-
if apexInfo.IsForPlatform() {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", dexOutputFile)
diff --git a/java/sdk_library_external.go b/java/sdk_library_external.go
index 2934936..0acaa13 100644
--- a/java/sdk_library_external.go
+++ b/java/sdk_library_external.go
@@ -75,10 +75,15 @@
return inList(j.Name(), ctx.Config().InterPartitionJavaLibraryAllowList())
}
+func (j *Module) syspropWithPublicStubs() bool {
+ return j.deviceProperties.SyspropPublicStub != ""
+}
+
type javaSdkLibraryEnforceContext interface {
Name() string
allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool
partitionGroup(ctx android.EarlyModuleContext) partitionGroup
+ syspropWithPublicStubs() bool
}
var _ javaSdkLibraryEnforceContext = (*Module)(nil)
@@ -88,6 +93,10 @@
return
}
+ if dep.syspropWithPublicStubs() {
+ return
+ }
+
// If product interface is not enforced, skip check between system and product partition.
// But still need to check between product and vendor partition because product interface flag
// just represents enforcement between product and system, and vendor interface enforcement
diff --git a/java/sysprop.go b/java/sysprop.go
deleted file mode 100644
index e41aef6..0000000
--- a/java/sysprop.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// 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
-
-// This file contains a map to redirect dependencies towards sysprop_library. If a sysprop_library
-// is owned by Platform, and the client module links against system API, the public stub of the
-// sysprop_library should be used. The map will contain public stub names of sysprop_libraries.
-
-import (
- "sync"
-
- "android/soong/android"
-)
-
-type syspropLibraryInterface interface {
- BaseModuleName() string
- Owner() string
- HasPublicStub() bool
- JavaPublicStubName() string
-}
-
-var (
- syspropPublicStubsKey = android.NewOnceKey("syspropPublicStubsJava")
- syspropPublicStubsLock sync.Mutex
-)
-
-func init() {
- android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_java", SyspropMutator).Parallel()
- })
-}
-
-func syspropPublicStubs(config android.Config) map[string]string {
- return config.Once(syspropPublicStubsKey, func() interface{} {
- return make(map[string]string)
- }).(map[string]string)
-}
-
-// gather list of sysprop libraries owned by platform.
-func SyspropMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(syspropLibraryInterface); ok {
- if m.Owner() != "Platform" || !m.HasPublicStub() {
- return
- }
-
- syspropPublicStubs := syspropPublicStubs(mctx.Config())
- syspropPublicStubsLock.Lock()
- defer syspropPublicStubsLock.Unlock()
-
- syspropPublicStubs[m.BaseModuleName()] = m.JavaPublicStubName()
- }
-}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 2ccce15..4ad68ea 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -37,9 +37,10 @@
}
type syspropGenProperties struct {
- Srcs []string `android:"path"`
- Scope string
- Name *string
+ Srcs []string `android:"path"`
+ Scope string
+ Name *string
+ Check_api *string
}
type syspropJavaGenRule struct {
@@ -68,10 +69,6 @@
func init() {
pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
-
- android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
- })
}
// syspropJavaGenRule module generates srcjar containing generated java APIs.
@@ -103,6 +100,12 @@
}
}
+func (g *syspropJavaGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Add a dependency from the stubs to sysprop library so that the generator rule can depend on
+ // the check API rule of the sysprop library.
+ ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
+}
+
func (g *syspropJavaGenRule) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
@@ -157,9 +160,6 @@
// If set to true, build a variant of the module for the host. Defaults to false.
Host_supported *bool
- // Whether public stub exists or not.
- Public_stub *bool `blueprint:"mutated"`
-
Cpp struct {
// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
// Forwarded to cc_library.min_sdk_version
@@ -202,11 +202,8 @@
return "lib" + m.BaseModuleName()
}
-func (m *syspropLibrary) JavaPublicStubName() string {
- if proptools.Bool(m.properties.Public_stub) {
- return m.BaseModuleName() + "_public"
- }
- return ""
+func (m *syspropLibrary) javaPublicStubName() string {
+ return m.BaseModuleName() + "_public"
}
func (m *syspropLibrary) javaGenModuleName() string {
@@ -221,10 +218,6 @@
return m.ModuleBase.Name()
}
-func (m *syspropLibrary) HasPublicStub() bool {
- return proptools.Bool(m.properties.Public_stub)
-}
-
func (m *syspropLibrary) CurrentSyspropApiFile() android.OptionalPath {
return m.currentApiFile
}
@@ -399,16 +392,17 @@
}
type javaLibraryProperties struct {
- Name *string
- Srcs []string
- Soc_specific *bool
- Device_specific *bool
- Product_specific *bool
- Required []string
- Sdk_version *string
- Installable *bool
- Libs []string
- Stem *string
+ Name *string
+ Srcs []string
+ Soc_specific *bool
+ Device_specific *bool
+ Product_specific *bool
+ Required []string
+ Sdk_version *string
+ Installable *bool
+ Libs []string
+ Stem *string
+ SyspropPublicStub string
}
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
@@ -490,35 +484,42 @@
// Contrast to C++, syspropJavaGenRule module will generate srcjar and the srcjar will be fed
// to Java implementation library.
ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
- Srcs: m.properties.Srcs,
- Scope: scope,
- Name: proptools.StringPtr(m.javaGenModuleName()),
- })
-
- ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
- Name: proptools.StringPtr(m.BaseModuleName()),
- Srcs: []string{":" + m.javaGenModuleName()},
- Soc_specific: proptools.BoolPtr(ctx.SocSpecific()),
- Device_specific: proptools.BoolPtr(ctx.DeviceSpecific()),
- Product_specific: proptools.BoolPtr(ctx.ProductSpecific()),
- Installable: m.properties.Installable,
- Sdk_version: proptools.StringPtr("core_current"),
- Libs: []string{javaSyspropStub},
+ Srcs: m.properties.Srcs,
+ Scope: scope,
+ Name: proptools.StringPtr(m.javaGenModuleName()),
+ Check_api: proptools.StringPtr(ctx.ModuleName()),
})
// if platform sysprop_library is installed in /system or /system-ext, we regard it as an API
// and allow any modules (even from different partition) to link against the sysprop_library.
// To do that, we create a public stub and expose it to modules with sdk_version: system_*.
+ var publicStub string
if isOwnerPlatform && installedInSystem {
- m.properties.Public_stub = proptools.BoolPtr(true)
+ publicStub = m.javaPublicStubName()
+ }
+
+ ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
+ Name: proptools.StringPtr(m.BaseModuleName()),
+ Srcs: []string{":" + m.javaGenModuleName()},
+ Soc_specific: proptools.BoolPtr(ctx.SocSpecific()),
+ Device_specific: proptools.BoolPtr(ctx.DeviceSpecific()),
+ Product_specific: proptools.BoolPtr(ctx.ProductSpecific()),
+ Installable: m.properties.Installable,
+ Sdk_version: proptools.StringPtr("core_current"),
+ Libs: []string{javaSyspropStub},
+ SyspropPublicStub: publicStub,
+ })
+
+ if publicStub != "" {
ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
- Srcs: m.properties.Srcs,
- Scope: "public",
- Name: proptools.StringPtr(m.javaGenPublicStubName()),
+ Srcs: m.properties.Srcs,
+ Scope: "public",
+ Name: proptools.StringPtr(m.javaGenPublicStubName()),
+ Check_api: proptools.StringPtr(ctx.ModuleName()),
})
ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
- Name: proptools.StringPtr(m.JavaPublicStubName()),
+ Name: proptools.StringPtr(publicStub),
Srcs: []string{":" + m.javaGenPublicStubName()},
Installable: proptools.BoolPtr(false),
Sdk_version: proptools.StringPtr("core_current"),
@@ -537,15 +538,3 @@
*libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName())
}
}
-
-// syspropDepsMutator adds dependencies from java implementation library to sysprop library.
-// java implementation library then depends on check API rule of sysprop library.
-func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
- if m, ok := ctx.Module().(*syspropLibrary); ok {
- ctx.AddReverseDependency(m, nil, m.javaGenModuleName())
-
- if proptools.Bool(m.properties.Public_stub) {
- ctx.AddReverseDependency(m, nil, m.javaGenPublicStubName())
- }
- }
-}
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 5cb9e64..9d914e3 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -26,7 +26,6 @@
"strings"
"testing"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -61,16 +60,10 @@
java.RegisterRequiredBuildComponentsForTest(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
- })
android.RegisterPrebuiltMutators(ctx)
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel()
- })
ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
@@ -392,15 +385,9 @@
}
// Java modules linking against system API should use public stub
- javaSystemApiClient := ctx.ModuleForTests("java-platform", "android_common")
- publicStubFound := false
- ctx.VisitDirectDeps(javaSystemApiClient.Module(), func(dep blueprint.Module) {
- if dep.Name() == "sysprop-platform_public" {
- publicStubFound = true
- }
- })
- if !publicStubFound {
- t.Errorf("system api client should use public stub")
+ javaSystemApiClient := ctx.ModuleForTests("java-platform", "android_common").Rule("javac")
+ syspropPlatformPublic := ctx.ModuleForTests("sysprop-platform_public", "android_common").Description("for turbine")
+ if g, w := javaSystemApiClient.Implicits.Strings(), syspropPlatformPublic.Output.String(); !android.InList(w, g) {
+ t.Errorf("system api client should use public stub %q, got %q", w, g)
}
-
}