Merge "Improve mixed builds error messages"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 2e4068d..24731e8 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -726,7 +726,6 @@
// aar support
"prebuilt_car-ui-androidx-core-common", // TODO(b/224773339), genrule dependency creates an .aar, not a .jar
- "prebuilt_platform-robolectric-4.4-prebuilt", // aosp/1999250, needs .aar support in Jars
"prebuilt_platform-robolectric-4.5.1-prebuilt", // aosp/1999250, needs .aar support in Jars
// ERROR: The dependencies for the following 1 jar(s) are not complete.
// 1.bazel-out/android_target-fastbuild/bin/prebuilts/tools/common/m2/_aar/robolectric-monitor-1.0.2-alpha1/classes_and_libs_merged.jar
@@ -1345,7 +1344,6 @@
"prebuilt_kotlin-stdlib-jdk8",
"prebuilt_kotlin-test",
// TODO(b/217750501) exclude_files property not supported
- "prebuilt_platform-robolectric-4.4-prebuilt",
"prebuilt_platform-robolectric-4.5.1-prebuilt",
"prebuilt_currysrc_org.eclipse",
}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index fd395a1..acb81a4 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -1050,18 +1050,26 @@
for _, depset := range ctx.Config().BazelContext.AqueryDepsets() {
var outputs []Path
+ var orderOnlies []Path
for _, depsetDepHash := range depset.TransitiveDepSetHashes {
otherDepsetName := bazelDepsetName(depsetDepHash)
outputs = append(outputs, PathForPhony(ctx, otherDepsetName))
}
for _, artifactPath := range depset.DirectArtifacts {
- outputs = append(outputs, PathForBazelOut(ctx, artifactPath))
+ pathInBazelOut := PathForBazelOut(ctx, artifactPath)
+ if artifactPath == "bazel-out/volatile-status.txt" {
+ // See https://bazel.build/docs/user-manual#workspace-status
+ orderOnlies = append(orderOnlies, pathInBazelOut)
+ } else {
+ outputs = append(outputs, pathInBazelOut)
+ }
}
thisDepsetName := bazelDepsetName(depset.ContentHash)
ctx.Build(pctx, BuildParams{
Rule: blueprint.Phony,
Outputs: []WritablePath{PathForPhony(ctx, thisDepsetName)},
Implicits: outputs,
+ OrderOnly: orderOnlies,
})
}
diff --git a/android/license.go b/android/license.go
index cde5e6e..ab8431a 100644
--- a/android/license.go
+++ b/android/license.go
@@ -15,10 +15,12 @@
package android
import (
- "android/soong/bazel"
"fmt"
- "github.com/google/blueprint"
"os"
+
+ "github.com/google/blueprint"
+
+ "android/soong/bazel"
)
type licenseKindDependencyTag struct {
@@ -101,6 +103,14 @@
}
func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
+ for i, license := range m.properties.License_kinds {
+ for j := i + 1; j < len(m.properties.License_kinds); j++ {
+ if license == m.properties.License_kinds[j] {
+ ctx.ModuleErrorf("Duplicated license kind: %q", license)
+ break
+ }
+ }
+ }
ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...)
}
diff --git a/android/license_test.go b/android/license_test.go
index 7222cd7..89e7f06 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -90,6 +90,36 @@
},
},
{
+ name: "must not duplicate license_kind",
+ fs: map[string][]byte{
+ "top/Android.bp": []byte(`
+ license_kind {
+ name: "top_by_exception_only",
+ conditions: ["by_exception_only"],
+ visibility: ["//visibility:private"],
+ }
+
+ license_kind {
+ name: "top_by_exception_only_2",
+ conditions: ["by_exception_only"],
+ visibility: ["//visibility:private"],
+ }
+
+ license {
+ name: "top_proprietary",
+ license_kinds: [
+ "top_by_exception_only",
+ "top_by_exception_only_2",
+ "top_by_exception_only"
+ ],
+ visibility: ["//visibility:public"],
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Android.bp:14:5: module "top_proprietary": Duplicated license kind: "top_by_exception_only"`,
+ },
+ },
+ {
name: "license_kind module must exist",
fs: map[string][]byte{
"top/Android.bp": []byte(`
diff --git a/android/neverallow.go b/android/neverallow.go
index 293bac8..ad9880a 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -59,6 +59,7 @@
AddNeverAllowRules(createInitFirstStageRules()...)
AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
AddNeverAllowRules(createBp2BuildRule())
+ AddNeverAllowRules(createCcStubsRule())
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -214,6 +215,17 @@
}
}
+func createCcStubsRule() Rule {
+ ccStubsImplementationInstallableProjectsAllowedList := []string{
+ "packages/modules/Virtualization/vm_payload",
+ }
+
+ return NeverAllow().
+ NotIn(ccStubsImplementationInstallableProjectsAllowedList...).
+ WithMatcher("stubs.implementation_installable", isSetMatcherInstance).
+ Because("implementation_installable can only be used in allowed projects.")
+}
+
func createUncompressDexRules() []Rule {
return []Rule{
NeverAllow().
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 4772799..5f5f9a1 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -367,6 +367,22 @@
"framework can't be used when building against SDK",
},
},
+ // Test for the rule restricting use of implementation_installable
+ {
+ name: `"implementation_installable" outside allowed list`,
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ cc_library {
+ name: "outside_allowed_list",
+ stubs: {
+ implementation_installable: true,
+ },
+ }`),
+ },
+ expectedErrors: []string{
+ `module "outside_allowed_list": violates neverallow`,
+ },
+ },
}
var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -419,6 +435,10 @@
Platform struct {
Shared_libs []string
}
+
+ Stubs struct {
+ Implementation_installable *bool
+ }
}
type mockCcLibraryModule struct {
diff --git a/apex/apex.go b/apex/apex.go
index 04808c1..b1b4e47 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2301,7 +2301,7 @@
//
// Always include if we are a host-apex however since those won't have any
// system libraries.
- if !am.DirectlyInAnyApex() {
+ if ch.IsStubsImplementationRequired() && !am.DirectlyInAnyApex() {
// we need a module name for Make
name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName
if !android.InList(name, a.requiredDeps) {
diff --git a/bazel/configurability.go b/bazel/configurability.go
index a93aa00..3f4cc73 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -203,6 +203,11 @@
osAndInApexMap = map[string]string{
AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex",
AndroidAndNonApex: "//build/bazel/rules/apex:android-non_apex",
+ osDarwin: "//build/bazel/platforms/os:darwin",
+ osLinux: "//build/bazel/platforms/os:linux",
+ osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
+ osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
+ osWindows: "//build/bazel/platforms/os:windows",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
}
diff --git a/bazel/properties.go b/bazel/properties.go
index 823cda8..ee9609a 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -843,6 +843,26 @@
// ResolveExcludes handles excludes across the various axes, ensuring that items are removed from
// the base value and included in default values as appropriate.
func (lla *LabelListAttribute) ResolveExcludes() {
+ // If there are OsAndInApexAxis, we need to use
+ // * includes from the OS & in APEX Axis for non-Android configs for libraries that need to be
+ // included in non-Android OSes
+ // * excludes from the OS Axis for non-Android configs, to exclude libraries that should _not_
+ // be included in the non-Android OSes
+ if _, ok := lla.ConfigurableValues[OsAndInApexAxis]; ok {
+ inApexLabels := lla.ConfigurableValues[OsAndInApexAxis][ConditionsDefaultConfigKey]
+ for config, labels := range lla.ConfigurableValues[OsConfigurationAxis] {
+ // OsAndroid has already handled its excludes.
+ // We only need to copy the excludes from other arches, so if there are none, skip it.
+ if config == OsAndroid || len(labels.Excludes) == 0 {
+ continue
+ }
+ lla.ConfigurableValues[OsAndInApexAxis][config] = LabelList{
+ Includes: inApexLabels.Includes,
+ Excludes: labels.Excludes,
+ }
+ }
+ }
+
for axis, configToLabels := range lla.ConfigurableValues {
baseLabels := lla.Value.deepCopy()
for config, val := range configToLabels {
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 8aa2c3e..68dc383 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -789,3 +789,82 @@
},
})
}
+
+func TestCcBinaryWithIntegerOverflowProperty(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary with integer overflow property specified",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ sanitize: {
+ integer_overflow: true,
+ },
+}`,
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "features": `["ubsan_integer_overflow"]`,
+ }},
+ },
+ })
+}
+
+func TestCcBinaryWithMiscUndefinedProperty(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary with miscellaneous properties specified",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+}`,
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ]`,
+ }},
+ },
+ })
+}
+
+func TestCcBinaryWithUBSanPropertiesArchSpecific(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary has correct feature select when UBSan props are specified in arch specific blocks",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+ target: {
+ android: {
+ sanitize: {
+ misc_undefined: ["alignment"],
+ },
+ },
+ linux_glibc: {
+ sanitize: {
+ integer_overflow: true,
+ },
+ },
+ },
+}`,
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ] + select({
+ "//build/bazel/platforms/os:android": ["ubsan_alignment"],
+ "//build/bazel/platforms/os:linux": ["ubsan_integer_overflow"],
+ "//conditions:default": [],
+ })`,
+ }},
+ },
+ })
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 4c86374..419baef 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -2976,6 +2976,63 @@
})
}
+func TestCcLibraryExcludesLibsHost(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Filesystem: map[string]string{
+ "bar.map.txt": "",
+ },
+ Blueprint: simpleModuleDoNotConvertBp2build("cc_library", "bazlib") + `
+cc_library {
+ name: "quxlib",
+ stubs: { symbol_file: "bar.map.txt", versions: ["current"] },
+ bazel_module: { bp2build_available: false },
+}
+cc_library {
+ name: "barlib",
+ stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: false },
+}
+cc_library {
+ name: "foolib",
+ shared_libs: ["barlib", "quxlib"],
+ target: {
+ host: {
+ shared_libs: ["bazlib"],
+ exclude_shared_libs: ["barlib"],
+ },
+ },
+ include_build_directory: false,
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/platforms/os:darwin": [":bazlib"],
+ "//build/bazel/platforms/os:linux": [":bazlib"],
+ "//build/bazel/platforms/os:linux_bionic": [":bazlib"],
+ "//build/bazel/platforms/os:linux_musl": [":bazlib"],
+ "//build/bazel/platforms/os:windows": [":bazlib"],
+ "//conditions:default": [],
+ }) + select({
+ "//build/bazel/platforms/os:darwin": [":quxlib"],
+ "//build/bazel/platforms/os:linux": [":quxlib"],
+ "//build/bazel/platforms/os:linux_bionic": [":quxlib"],
+ "//build/bazel/platforms/os:linux_musl": [":quxlib"],
+ "//build/bazel/platforms/os:windows": [":quxlib"],
+ "//build/bazel/rules/apex:android-in_apex": [
+ ":barlib_stub_libs_current",
+ ":quxlib_stub_libs_current",
+ ],
+ "//conditions:default": [
+ ":barlib",
+ ":quxlib",
+ ],
+ })`,
+ }),
+ })
+}
+
func TestCcLibraryEscapeLdflags(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
ModuleTypeUnderTest: "cc_library",
@@ -3543,3 +3600,113 @@
},
})
}
+
+func TestCcLibraryWithIntegerOverflowProperty(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library has correct features when integer_overflow property is provided",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ sanitize: {
+ integer_overflow: true,
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "features": `["ubsan_integer_overflow"]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `["ubsan_integer_overflow"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithMiscUndefinedProperty(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library has correct features when misc_undefined property is provided",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithUBSanPropertiesArchSpecific(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library has correct feature select when UBSan props are specified in arch specific blocks",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+ target: {
+ android: {
+ sanitize: {
+ misc_undefined: ["alignment"],
+ },
+ },
+ linux_glibc: {
+ sanitize: {
+ integer_overflow: true,
+ },
+ },
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ] + select({
+ "//build/bazel/platforms/os:android": ["ubsan_alignment"],
+ "//build/bazel/platforms/os:linux": ["ubsan_integer_overflow"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ] + select({
+ "//build/bazel/platforms/os:android": ["ubsan_alignment"],
+ "//build/bazel/platforms/os:linux": ["ubsan_integer_overflow"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index b86f607..8ef7d16 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -845,3 +845,85 @@
},
})
}
+
+func TestCcLibrarySharedWithIntegerOverflowProperty(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared has correct features when integer_overflow property is provided",
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ sanitize: {
+ integer_overflow: true,
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `["ubsan_integer_overflow"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedWithMiscUndefinedProperty(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared has correct features when misc_undefined property is provided",
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedWithUBSanPropertiesArchSpecific(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared has correct feature select when UBSan props are specified in arch specific blocks",
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+ target: {
+ android: {
+ sanitize: {
+ misc_undefined: ["alignment"],
+ },
+ },
+ linux_glibc: {
+ sanitize: {
+ integer_overflow: true,
+ },
+ },
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ] + select({
+ "//build/bazel/platforms/os:android": ["ubsan_alignment"],
+ "//build/bazel/platforms/os:linux": ["ubsan_integer_overflow"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index b47d1f1..cac7f9b 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1723,3 +1723,85 @@
},
})
}
+
+func TestCcLibraryStaticWithIntegerOverflowProperty(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static has correct features when integer_overflow property is provided",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ sanitize: {
+ integer_overflow: true,
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "features": `["ubsan_integer_overflow"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryStaticWithMiscUndefinedProperty(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static has correct features when misc_undefined property is provided",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryStaticWithUBSanPropertiesArchSpecific(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static has correct feature select when UBSan props are specified in arch specific blocks",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ sanitize: {
+ misc_undefined: ["undefined", "nullability"],
+ },
+ target: {
+ android: {
+ sanitize: {
+ misc_undefined: ["alignment"],
+ },
+ },
+ linux_glibc: {
+ sanitize: {
+ integer_overflow: true,
+ },
+ },
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "features": `[
+ "ubsan_undefined",
+ "ubsan_nullability",
+ ] + select({
+ "//build/bazel/platforms/os:android": ["ubsan_alignment"],
+ "//build/bazel/platforms/os:linux": ["ubsan_integer_overflow"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 3750804..0f1a8b2 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -90,6 +90,7 @@
}
func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
+ t.Helper()
bp2buildSetup := func(ctx *android.TestContext) {
registerModuleTypes(ctx)
ctx.RegisterForBazelConversion()
@@ -98,6 +99,7 @@
}
func RunApiBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
+ t.Helper()
apiBp2BuildSetup := func(ctx *android.TestContext) {
registerModuleTypes(ctx)
ctx.RegisterForApiBazelConversion()
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 6caa854..d41aa00 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -341,7 +341,7 @@
compilerAttributes
linkerAttributes
- // A combination of compilerAttributes.features and linkerAttributes.features
+ // A combination of compilerAttributes.features and linkerAttributes.features, as well as sanitizer features
features bazel.StringListAttribute
protoDependency *bazel.LabelAttribute
aidlDependency *bazel.LabelAttribute
@@ -781,7 +781,7 @@
(&linkerAttrs).wholeArchiveDeps.Add(bp2buildCcSysprop(ctx, module.Name(), module.Properties.Min_sdk_version, compilerAttrs.syspropSrcs))
}
- features := compilerAttrs.features.Clone().Append(linkerAttrs.features)
+ features := compilerAttrs.features.Clone().Append(linkerAttrs.features).Append(bp2buildSanitizerFeatures(ctx, module))
features.DeduplicateAxesFromBase()
return baseAttributes{
@@ -1364,3 +1364,20 @@
return attrs
}
+
+func bp2buildSanitizerFeatures(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute {
+ sanitizerFeatures := bazel.StringListAttribute{}
+ bp2BuildPropParseHelper(ctx, m, &SanitizeProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ var features []string
+ if sanitizerProps, ok := props.(*SanitizeProperties); ok {
+ if sanitizerProps.Sanitize.Integer_overflow != nil && *sanitizerProps.Sanitize.Integer_overflow {
+ features = append(features, "ubsan_integer_overflow")
+ }
+ for _, sanitizer := range sanitizerProps.Sanitize.Misc_undefined {
+ features = append(features, "ubsan_"+sanitizer)
+ }
+ sanitizerFeatures.SetSelectValue(axis, config, features)
+ }
+ })
+ return sanitizerFeatures
+}
diff --git a/cc/cc.go b/cc/cc.go
index 306e483..8b3f456 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1205,6 +1205,8 @@
return c
}
+// UseVndk() returns true if this module is built against VNDK.
+// This means the vendor and product variants of a module.
func (c *Module) UseVndk() bool {
return c.Properties.VndkVersion != ""
}
@@ -1298,6 +1300,9 @@
return false
}
+// IsVndk() returns true if this module has a vndk variant.
+// Note that IsVndk() returns true for all variants of vndk-enabled libraries. Not only vendor variant,
+// but also platform and product variants of vndk-enabled libraries return true for IsVndk().
func (c *Module) IsVndk() bool {
if vndkdep := c.vndkdep; vndkdep != nil {
return vndkdep.isVndk()
@@ -1376,6 +1381,13 @@
return false
}
+func (c *Module) IsStubsImplementationRequired() bool {
+ if lib := c.library; lib != nil {
+ return lib.isStubsImplementationRequired()
+ }
+ return false
+}
+
// If this is a stubs library, ImplementationModuleName returns the name of the module that contains
// the implementation. If it is an implementation library it returns its own name.
func (c *Module) ImplementationModuleName(ctx android.BaseModuleContext) string {
diff --git a/cc/library.go b/cc/library.go
index b639930..0729ff4 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -71,6 +71,12 @@
// List versions to generate stubs libs for. The version name "current" is always
// implicitly added.
Versions []string
+
+ // Whether to not require the implementation of the library to be installed if a
+ // client of the stubs is installed. Defaults to true; set to false if the
+ // implementation is made available by some other means, e.g. in a Microdroid
+ // virtual machine.
+ Implementation_installable *bool
}
// set the name of the output
@@ -1339,6 +1345,7 @@
buildStubs() bool
setBuildStubs(isLatest bool)
hasStubsVariants() bool
+ isStubsImplementationRequired() bool
setStubsVersion(string)
stubsVersion() string
@@ -2298,6 +2305,10 @@
len(library.Properties.Stubs.Versions) > 0
}
+func (library *libraryDecorator) isStubsImplementationRequired() bool {
+ return BoolDefault(library.Properties.Stubs.Implementation_installable, true)
+}
+
func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
if !library.hasStubsVariants() {
return nil
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index c420567..82db634 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -132,21 +132,21 @@
*android_bundle_proto.ApkDescription
}
-func (m apkDescriptionMatcher) matches(config TargetConfig) bool {
- return m.ApkDescription == nil || (apkTargetingMatcher{m.Targeting}).matches(config)
+func (m apkDescriptionMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
+ return m.ApkDescription == nil || (apkTargetingMatcher{m.Targeting}).matches(config, allAbisMustMatch)
}
type apkTargetingMatcher struct {
*android_bundle_proto.ApkTargeting
}
-func (m apkTargetingMatcher) matches(config TargetConfig) bool {
+func (m apkTargetingMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
return m.ApkTargeting == nil ||
(abiTargetingMatcher{m.AbiTargeting}.matches(config) &&
languageTargetingMatcher{m.LanguageTargeting}.matches(config) &&
screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) &&
sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) &&
- multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config))
+ multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config, allAbisMustMatch))
}
type languageTargetingMatcher struct {
@@ -215,33 +215,27 @@
}
}
- m = append(multiAbiValue{}, m...)
- sort.Slice(m, sortAbis(m))
- other = append(multiAbiValue{}, other...)
- sort.Slice(other, sortAbis(other))
+ sortedM := append(multiAbiValue{}, m...)
+ sort.Slice(sortedM, sortAbis(sortedM))
+ sortedOther := append(multiAbiValue{}, other...)
+ sort.Slice(sortedOther, sortAbis(sortedOther))
- for i := 0; i < min(len(m), len(other)); i++ {
- if multiAbiPriorities[m[i].Alias] > multiAbiPriorities[other[i].Alias] {
+ for i := 0; i < min(len(sortedM), len(sortedOther)); i++ {
+ if multiAbiPriorities[sortedM[i].Alias] > multiAbiPriorities[sortedOther[i].Alias] {
return 1
}
- if multiAbiPriorities[m[i].Alias] < multiAbiPriorities[other[i].Alias] {
+ if multiAbiPriorities[sortedM[i].Alias] < multiAbiPriorities[sortedOther[i].Alias] {
return -1
}
}
- if len(m) == len(other) {
- return 0
- }
- if len(m) > len(other) {
- return 1
- }
- return -1
+ return len(sortedM) - len(sortedOther)
}
// this logic should match the logic in bundletool at
// https://github.com/google/bundletool/blob/ae0fc0162fd80d92ef8f4ef4527c066f0106942f/src/main/java/com/android/tools/build/bundletool/device/MultiAbiMatcher.java#L43
// (note link is the commit at time of writing; but logic should always match the latest)
-func (t multiAbiTargetingMatcher) matches(config TargetConfig) bool {
+func (t multiAbiTargetingMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
if t.MultiAbiTargeting == nil {
return true
}
@@ -250,12 +244,19 @@
}
multiAbiIsValid := func(m multiAbiValue) bool {
+ numValid := 0
for _, abi := range m {
- if _, ok := config.abis[abi.Alias]; !ok {
- return false
+ if _, ok := config.abis[abi.Alias]; ok {
+ numValid += 1
}
}
- return true
+ if numValid == 0 {
+ return false
+ } else if numValid > 0 && !allAbisMustMatch {
+ return true
+ } else {
+ return numValid == len(m)
+ }
}
// ensure that the current value is valid for our config
@@ -264,6 +265,7 @@
for _, multiAbi := range multiAbiSet {
if multiAbiIsValid(multiAbi.GetAbi()) {
valueSetContainsViableAbi = true
+ break
}
}
@@ -362,13 +364,13 @@
*android_bundle_proto.VariantTargeting
}
-func (m variantTargetingMatcher) matches(config TargetConfig) bool {
+func (m variantTargetingMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
if m.VariantTargeting == nil {
return true
}
return sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) &&
abiTargetingMatcher{m.AbiTargeting}.matches(config) &&
- multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config) &&
+ multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config, allAbisMustMatch) &&
screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) &&
textureCompressionFormatTargetingMatcher{m.TextureCompressionFormatTargeting}.matches(config)
}
@@ -380,30 +382,42 @@
// Return all entries matching target configuration
func selectApks(toc Toc, targetConfig TargetConfig) SelectionResult {
- var result SelectionResult
- for _, variant := range (*toc).GetVariant() {
- if !(variantTargetingMatcher{variant.GetTargeting()}.matches(targetConfig)) {
- continue
- }
- for _, as := range variant.GetApkSet() {
- if !(moduleMetadataMatcher{as.ModuleMetadata}.matches(targetConfig)) {
+ checkMatching := func(allAbisMustMatch bool) SelectionResult {
+ var result SelectionResult
+ for _, variant := range (*toc).GetVariant() {
+ if !(variantTargetingMatcher{variant.GetTargeting()}.matches(targetConfig, allAbisMustMatch)) {
continue
}
- for _, apkdesc := range as.GetApkDescription() {
- if (apkDescriptionMatcher{apkdesc}).matches(targetConfig) {
- result.entries = append(result.entries, apkdesc.GetPath())
- // TODO(asmundak): As it turns out, moduleName which we get from
- // the ModuleMetadata matches the module names of the generated
- // entry paths just by coincidence, only for the split APKs. We
- // need to discuss this with bundletool folks.
- result.moduleName = as.GetModuleMetadata().GetName()
+ for _, as := range variant.GetApkSet() {
+ if !(moduleMetadataMatcher{as.ModuleMetadata}.matches(targetConfig)) {
+ continue
+ }
+ for _, apkdesc := range as.GetApkDescription() {
+ if (apkDescriptionMatcher{apkdesc}).matches(targetConfig, allAbisMustMatch) {
+ result.entries = append(result.entries, apkdesc.GetPath())
+ // TODO(asmundak): As it turns out, moduleName which we get from
+ // the ModuleMetadata matches the module names of the generated
+ // entry paths just by coincidence, only for the split APKs. We
+ // need to discuss this with bundletool folks.
+ result.moduleName = as.GetModuleMetadata().GetName()
+ }
+ }
+ // we allow only a single module, so bail out here if we found one
+ if result.moduleName != "" {
+ return result
}
}
- // we allow only a single module, so bail out here if we found one
- if result.moduleName != "" {
- return result
- }
}
+ return result
+ }
+ result := checkMatching(true)
+ if result.moduleName == "" {
+ // if there are no matches where all of the ABIs are available in the
+ // TargetConfig, then search again with a looser requirement of at
+ // least one matching ABI
+ // NOTE(b/260130686): this logic diverges from the logic in bundletool
+ // https://github.com/google/bundletool/blob/ae0fc0162fd80d92ef8f4ef4527c066f0106942f/src/main/java/com/android/tools/build/bundletool/device/MultiAbiMatcher.java#L43
+ result = checkMatching(false)
}
return result
}
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index c1d712d..9f52877 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -744,7 +744,11 @@
bp.Abi_X86_64: 0,
},
},
- expected: SelectionResult{},
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-x86.x86_64.apex",
+ }},
},
{
name: "multi-variant multi-target cross-target",
diff --git a/java/fuzz_test.go b/java/fuzz_test.go
index 6e5d912..186c3aa 100644
--- a/java/fuzz_test.go
+++ b/java/fuzz_test.go
@@ -88,7 +88,7 @@
expected := "lib64/libjni.so"
if runtime.GOOS == "darwin" {
- expected = "libjni.dylib"
+ expected = "lib64/libjni.dylib"
}
fooJniFilePaths := foo.jniFilePaths